【发布时间】:2012-10-02 00:39:26
【问题描述】:
当我们分配这样的值时是否会降低性能?
Dropdown1.Enable = dropdown2.Enable = dropdown3.Enable = false;
提前致谢。
【问题讨论】:
-
不知道为什么这个问题被标记为过于本地化。这是相当实用的,而不是“本地化”的 IMO。
标签: c# performance-testing assignment-operator
当我们分配这样的值时是否会降低性能?
Dropdown1.Enable = dropdown2.Enable = dropdown3.Enable = false;
提前致谢。
【问题讨论】:
标签: c# performance-testing assignment-operator
答案是没有影响——相当于三个赋值语句。
甚至没有调用任何get 操作,如下所示:
控制台应用项目:
using System;
using System.Diagnostics;
namespace ConsoleApplication5
{
public class X
{
private int _a;
private int _b;
public int A
{
get
{
Console.WriteLine("get A");
return _a + 1;
}
set
{
Console.WriteLine("set A");
_a = value;
}
}
public int B
{
get
{
Console.WriteLine("get B");
return _b + 2;
}
set
{
Console.WriteLine("set B");
_b = value;
}
}
}
class Program
{
static void Main(string[] args)
{
var x = new X();
Console.WriteLine("Assign");
int y = x.B = x.A = 125;
Console.WriteLine("Read");
Console.WriteLine("y " + y + " x.B " + x.B + " x.A " + x.A);
Console.ReadLine();
}
}
}
生成:
Assign
set A
set B
Read
get B
get A
y 125 x.B 127 x.A 126
请注意,在分配阶段,不会调用任何“get”,即使 A 和 B 的 getter 返回的值与设置在它们上的值不同,最终分配给 y 的值是源值表达式的 RHS。
【讨论】:
我可能对其他两个答案有误解,但我认为没有任何getters 被解雇。在所有三种情况下,为属性触发的是 setter。此外,我很确定 IL 只是将 false 值推入堆栈三次,并为每次触发一次设置器。
对于以下课程:
public class Test
{
public bool Prop { get; set; }
}
对于t1.Prop = t2.Prop = t3.Prop = false;,IL 是:
IL_0013: ldloc.0 //t1
IL_0014: ldloc.1 //t2
IL_0015: ldloc.2 //t2
IL_0016: ldc.i4.0 //false
IL_0017: dup //dup the false on the stack
IL_0018: stloc.3
IL_0019: callvirt UserQuery+Test.set_Prop //set value
IL_001E: nop
IL_001F: ldloc.3
IL_0020: dup //dup the false on the stack
IL_0021: stloc.3
IL_0022: callvirt UserQuery+Test.set_Prop //set value
IL_0027: nop
IL_0028: ldloc.3
IL_0029: callvirt UserQuery+Test.set_Prop //set value
为:
t1.Prop = false;
t2.Prop = false;
t3.Prop = false;
IL 是:
IL_0012: stloc.2
IL_0013: ldloc.0
IL_0014: ldc.i4.0 //false
IL_0015: callvirt UserQuery+Test.set_Prop //set value
IL_001A: nop
IL_001B: ldloc.1
IL_001C: ldc.i4.0 //false
IL_001D: callvirt UserQuery+Test.set_Prop //set value
IL_0022: nop
IL_0023: ldloc.2
IL_0024: ldc.i4.0 //false
IL_0025: callvirt UserQuery+Test.set_Prop //set value
所以 IL 非常接近,真正唯一的区别是点击 ldc.i4.0 三次,或者点击一次并在堆栈上复制两次。性能无关紧要。但是,如果获得 false 值是一项不平凡的操作,则将其放在三行上需要更长的时间,但您可以轻松编写:
bool value = SomeLongOperation();
t1.Prop = value;
t2.Prop = value;
t3.Prop = value;
因此,请尽一切可能提高公司的可读性和/或您的标准。
编辑:实际上,如果编译器/JIT 将单独的行条目优化为基本上第一种情况(或更快的情况)或其他优化状态,我不会感到惊讶。真的,唯一需要关心的是最后一个代码示例;如果你需要做SomeLongOperation() 来获取价值,只做一次。之后,做任何可读的事情。
【讨论】:
你通常会这样做:
variable1 = varaible2 = variable3 = 123
但是由于Enable 属性是一个getter,所以这是不可能的。
在内部,getter 看起来像这样:
public bool Enabled
{
get
{
return something;
}
set
{
something = value;
}
}
【讨论】: