我在某处读到:
良好做法: exp += val
糟糕的做法: exp = exp + val
第二个选项强制JIT评估exp
的两个副本,并且很多时候不需要这样做。第一个语句可以比第二个语句优化得更好,因为JIT可以避免两次评估exp。
所以我写了一个示例测试来验证这一点。但我得到的结果是我能得出结论。任何人都可以帮助我理解上面的一个是好的还是坏的做法,或者我的例子中有任何错误。
static void Main(string[] args)
{
DateTime startTime;
DateTime endTime;
for (int run = 0; run < 10; run++)
{
Console.WriteLine("--- Run #" + run.ToString());
long sumB = 0;
startTime = DateTime.Now;
for (long i = 0; i < 1000000000; i++)
{
sumB = sumB + 2L;
}
endTime = DateTime.Now;
Console.WriteLine(endTime - startTime);
long sumA = 0;
startTime = DateTime.Now;
for (long j = 0; j < 1000000000; j++)
{
sumA += 2L;
}
endTime = DateTime.Now;
Console.WriteLine(endTime - startTime);
}
Console.WriteLine("*");
Console.ReadKey();
}
答案 0 :(得分:5)
至少在C ++中(我不知道C#),a += b
只会评估a
一次,而a = a + b
会评估两次。
如果它是一个复杂的表达,那么这可能会对性能产生影响。如果像在你的例子中那样,它是一个简单的变量(或者更一般地说,是一个编译器可以证明没有副作用的表达式),那么两者都应该被优化以产生相同的代码,所以那里有#s; s可能没有显着差异。
更好的建议是支持a += b
,因为它可以避免冗余,帮助提高可读性并减少错误的范围,而不是使用(通常是假的或不相关的)关于性能的论据。
答案 1 :(得分:2)
a += b
仅在
时评估每个表达式一次a = a + b
评估两次。 a
可能是一个昂贵的表达式(不是局部变量):
int[] GetArray() { return new int[100000]; }
GetArray()[0] += 1;
与
非常不同GetArray()[0] = GetArray()[0] + 1;
并且在这种情况下在语义上不同,但这不是重点。假设GetArray
很贵。
这是一种罕见的情况,我只是说,因为你问的是性能。通常情况下,您只是出于文体学原因而写出复合作业表格,这是主观的。
为了好玩,我们可以深入了解该数组示例的工作原理。 C#编译器将发出IL,用于计算给定数组元素的托管指针(&#34;内部指针&#34;),然后它将评估右侧,它使用指针将结果存储到数组中。
令人惊讶的是,在IL级别,托管指针很常见。 C#使你屏蔽它。