排除'Else'条款会有性能差异吗?

时间:2009-09-23 18:01:44

标签: c# .net

以下两段代码之间是否存在性能差异?

if (myCondition)
{
     return "returnVal1";
}

return "returnVal2"

if (myCondition)
{
     return "returnVal1";
}
else
{
     return "returnVal2";
}

我的直觉是编译器应该对此进行优化,并且应该没有区别,但我经常看到它在我们的代码中完成了两种方式。我想知道它是否归结为偏好和可读性。

8 个答案:

答案 0 :(得分:13)

我很确定编译器会优化它。为您做最具可读性/遵循惯例的事情,并让编译器处理类似的简单事情。

即使没有进行优化,性能差异也可以忽略不计。

答案 1 :(得分:12)

找出答案的最佳方法是查看代码!这是VS2005 C#在发布模式下生成的代码:

    static bool F1 (int condition)
    {
      if (condition > 100)
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  mov         dword ptr [ebp-4],ecx 
00000007  cmp         dword ptr ds:[009185C8h],0 
0000000e  je          00000015 
00000010  call        79469149 
00000015  cmp         dword ptr [ebp-4],64h 
00000019  jle         00000024 
      {
        return true;
0000001b  mov         eax,1 
00000020  mov         esp,ebp 
00000022  pop         ebp  
00000023  ret              
      }

      return false;
00000024  xor         eax,eax 
00000026  mov         esp,ebp 
00000028  pop         ebp  
00000029  ret              
            }

    static bool F2 (int condition)
    {
      if (condition > 100)
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  mov         dword ptr [ebp-4],ecx 
00000007  cmp         dword ptr ds:[009185C8h],0 
0000000e  je          00000015 
00000010  call        79469109 
00000015  cmp         dword ptr [ebp-4],64h 
00000019  jle         00000024 
      {
        return true;
0000001b  mov         eax,1 
00000020  mov         esp,ebp 
00000022  pop         ebp  
00000023  ret              
      }
      else
      {
        return false;
00000024  xor         eax,eax 
00000026  mov         esp,ebp 
00000028  pop         ebp  
00000029  ret              
            }

这表明两个版本生成完全相同的代码,正如您所希望的那样。我还尝试了第三种选择:

    static bool F3 (int condition)
    {
      return condition > 100;
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  mov         dword ptr [ebp-4],ecx 
00000007  cmp         dword ptr ds:[009185C8h],0 
0000000e  je          00000015 
00000010  call        794690C9 
00000015  cmp         dword ptr [ebp-4],64h 
00000019  setg        al   
0000001c  movzx       eax,al 
0000001f  mov         esp,ebp 
00000021  pop         ebp  
00000022  ret              
            }

效率更高,因为它永远不会分支(分支通常很糟糕!)。

修改

实际上,找出哪个更有效的最好方法是分析代码,而不是查看汇编程序。

此外,它生成的代码非常不寻常。 push eax / mov [],ecx位是相同的,当然,作为单推ecx。此外,它通过寄存器传递然后将值存储在堆栈上。我想知道在调试器中运行代码来查看汇编程序是否正在改变代码的生成方式。

答案 2 :(得分:5)

虽然优化是一件好事,但可读性也很重要,所以如果你认为有助于提高可读性,那么它比你节省的纳秒更好。 IMHO

答案 3 :(得分:4)

如果您的编译器没有将它优化为相同的字节码,请将其抛出窗口!

答案 4 :(得分:2)

如果性能受到影响并且代码表明没有。

,我会非常惊讶

经过多年尝试找出遗留代码,其中多个编码器试图在编辑器中优化表达式并产生了令人难以理解的难以理解的代码,我只能说你应该写出有意义的东西并表达你想要的东西。最简单,最清晰的方式。

所有代码片段都很容易理解,因为它们很小但是想象逻辑分散在几页......

答案 5 :(得分:1)

您可以通过创建包含这两个变体的测试项目来自行发现。然后,在ildsamReflector中打开项目以查看反汇编。你会知道完全当时发生了什么。

答案 6 :(得分:0)

关于这个问题,除非你总是评估的案例是else条款,否则它不会有性能问题。

如评论中所述,您应该返回myCondition。但是,为了便于阅读,您应始终包含else子句。如果其他什么都不做,那么请说明:

//do nothing

它帮助开发人员在编写代码之后查看代码,以了解其他情况,但是没有存在的情况。这也是一个记录为什么没有其他的好地方。

性能受到影响的示例如下:

int x = 2;

if x != 2 {
     return true;
} else {
     return false;
}

它将始终检查if子句失败,因此必须检查else子句。

编辑:如果else子句什么都不做,编译器将跳过它 - 它只是为了阅读其他开发人员的目的而派上用场。它还可以使您的代码更简洁:

if(x=2) {
      doThis();
}
if(x!=2){
      doThat();
}

可能会让人感到困惑,很容易合并到:

if(x==2){
     doThis(); 
} else {
     doThat();
}

答案 7 :(得分:0)

此外,最佳做法是拥有一条返回路径,而不是多条返回路径。

if (myCondition)
{     return true;}
else
{     return false;}

应该是:

bool myResult = false;
if (myCondition)
     myResult = true;
return myResult;

当你开始在同一个方法中引入多个返回路径时,即使是简单的方法,也会使调试成倍地复杂化。

至于哪个是“更好”,我相信编译器处理两者(使用和不使用else),因为else是单个语句。

相关问题