C# ?:运算符与If语句性能
我一直在尝试优化我的代码,使其更加简洁易读,并希望这样做不会导致性能下降。我想我的更改可能会减慢我的应用程序,但它可能只是在我的脑海中。以下各项之间是否存在性能差异:C# ?:运算符与If语句性能,c#,.net,performance,if-statement,operators,C#,.net,Performance,If Statement,Operators,我一直在尝试优化我的代码,使其更加简洁易读,并希望这样做不会导致性能下降。我想我的更改可能会减慢我的应用程序,但它可能只是在我的脑海中。以下各项之间是否存在性能差异: Command.Parameters["@EMAIL"].Value = email ?? String.Empty; 及 及 我对可读性的偏好是空合并运算符,我只是不希望它影响性能。IMHO,优化可读性和可理解性—与您在几个月后回到这段代码并尝试了解您最初在做什么时在现实世界中花费的时间相比,任何运行时性能的提高都可能是最小的
Command.Parameters["@EMAIL"].Value = email ?? String.Empty;
及
及
我对可读性的偏好是空合并运算符,我只是不希望它影响性能。IMHO,优化可读性和可理解性—与您在几个月后回到这段代码并尝试了解您最初在做什么时在现实世界中花费的时间相比,任何运行时性能的提高都可能是最小的。我怀疑不会有任何性能差异 除此之外,我想知道,在这种情况下,你为什么会担心支持一种说法而不是另一种?我的意思是:性能影响(如果有)将是最小的。嗯,这将是一种微观优化,不值得这么做。
我会选择最具可读性、最清晰且不担心性能的语句,因为它的影响最小(在本例中)。在本例中,几乎没有显著的性能差异 当性能差异可以忽略不计时,这一切都是关于您在这里尝试的可读代码,这通常是一个很大的禁忌。除非您有性能分析表明这是一个问题,否则它甚至不值得更改 对于一般用途,正确答案是更容易维护的 不过,对于空合并运算符,IL是:
L_0001: ldsfld string ConsoleApplication2.Program::myString
L_0006: dup
L_0007: brtrue.s L_000f
L_0009: pop
L_000a: ldsfld string [mscorlib]System.String::Empty
L_000f: stloc.0
开关的IL为:
L_0001: ldsfld string ConsoleApplication2.Program::myString
L_0006: brfalse.s L_000f
L_0008: ldsfld string ConsoleApplication2.Program::myString
L_000d: br.s L_0014
L_000f: ldsfld string [mscorlib]System.String::Empty
L_0014: stloc.0
对于,如果值为null
,则执行六条语句,而对于执行四条操作
在notnull
值的情况下,null合并运算符执行四个操作,而不是五个操作
当然,这假设所有IL操作都需要相同的时间,但事实并非如此
无论如何,希望你能看到在这个微观尺度上的优化是如何开始迅速减少回报的
也就是说,在大多数情况下,在这种情况下,最容易阅读和维护的内容是正确的答案
如果您发现这样做的规模证明是低效的(而且这种情况非常少),那么您应该衡量哪种情况具有更好的性能,然后进行特定的优化
我想我的变化可能已经变慢了
关闭我的应用程序,但它可能只是
在我脑子里
除非你真的在衡量业绩,否则一切都在你的脑子里,都是无聊的猜测
(不是特别挑剔你,但是看到一个又一个关于性能微优化的问题(以及许多答案)没有包含“度量”一词,令人失望。这是一个机器级代码是高效的还是人类可读的代码的问题。
当我们让它更具可读性时,它使机器能够对代码进行复杂的解释,反之亦然……为了便于讨论。。。if/then/else的运行速度与?:三值操作的运行速度与单级开关/case语句的运行速度一样快 只有当您在案例陈述中开始深入到2-3个级别时,性能才会开始受到严重影响。就是像这个荒谬的例子,
switch (x % 3)
{
case 0:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 1:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 2:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
default:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
}
它最初的编写方式是一堆if语句,当我修改它时,程序的性能似乎受到了一些影响。也许这是一个孤立的事件,但它比任何事情都更激发了我的兴趣。“L_0006:dup”-在这里显示我自己的无知,但为什么它需要在这里重复呢?哦,我明白了。如果它不为空,则存储在000f,并且不会弹出。有道理。string.IsNullOrEmpty()呢?@SkippyFire:这将需要更多的IL指令,因为必须进行方法调用,并且它只会执行类似于上面的操作。方法调用可能会在JIT时内联,不是吗?当然,请记住,很多程序员都可以读取?:语句的速度与常规if语句一样快。在某些情况下,它们甚至比不使用大括号的if/else语句更清晰。我同意。这里的许多帖子都是关于性能的问题,询问一些无关紧要的小调整(++比+=1快吗?)。速度来自算法的复杂性:减少大量内存拷贝,快速搜索容器,适当地散列。小的调整对性能没有影响。-1:虽然chublogga的观点都是真实有效的,措辞也很好,但它们并没有回答最初的问题。OP是一个成年人,他可以做出自己的架构/可读性选择,而casperOne的回答实际上是对性能这一特定问题的一个更有趣、更直接的回答。我没有回答最初的问题,因为这是一个错误的问题。假设一个人可以看到显而易见的东西,这难道不安全吗,编译器应该足够聪明,能够看到这一点,甚至更进一步?我会将其细化为“在没有显著性能差异的情况下,这都是关于可读代码的。”有时,会有性能差异,有时这种差异是显著的,在这种情况下,代码可读性可能会退居次要位置。这与我所说的有什么不同吗?@chris ballance区别显然在于强调的地方。
L_0001: ldsfld string ConsoleApplication2.Program::myString
L_0006: brfalse.s L_000f
L_0008: ldsfld string ConsoleApplication2.Program::myString
L_000d: br.s L_0014
L_000f: ldsfld string [mscorlib]System.String::Empty
L_0014: stloc.0
switch (x % 3)
{
case 0:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 1:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 2:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
default:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
}