Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回内部if块与写入if/else块之间是否存在性能差异?_C#_Performance_If Statement_Return - Fatal编程技术网

C# 返回内部if块与写入if/else块之间是否存在性能差异?

C# 返回内部if块与写入if/else块之间是否存在性能差异?,c#,performance,if-statement,return,C#,Performance,If Statement,Return,我正在进行重构代码的项目,并意识到我写了如下内容: if(errorCode > 0) { DisplayError(errorCode); return; } // Continue to do stuff otherwise. if (errorCode > 0) { 011A00DA in al,dx 011A00DB push eax 011A00DC mov dword p

我正在进行重构代码的项目,并意识到我写了如下内容:

if(errorCode > 0)
{
   DisplayError(errorCode);
   return;
}

// Continue to do stuff otherwise.
            if (errorCode > 0) {
011A00DA  in          al,dx  
011A00DB  push        eax  
011A00DC  mov         dword ptr [ebp-4],ecx  
011A00DF  cmp         dword ptr ds:[10F3178h],0  
011A00E6  je          011A00ED  
011A00E8  call        7470C310  
011A00ED  cmp         dword ptr [ebp-4],0  
011A00F1  jle         011A0100  
                Console.WriteLine(errorCode);
011A00F3  mov         ecx,dword ptr [ebp-4]  
011A00F6  call        73C5A920  
                return;
011A00FB  nop  
011A00FC  mov         esp,ebp  
011A00FE  pop         ebp  
011A00FF  ret  
            }
            Console.WriteLine("ok");
011A0100  mov         ecx,dword ptr ds:[3E92190h]  
011A0106  call        7359023C  
        }
011A010B  nop  
011A010C  mov         esp,ebp  
011A010E  pop         ebp  
011A010F  ret
正如您可能猜到的,函数的返回类型为void。当我开始仔细考虑这一点时,我思考将其放在if/else块中是否有真正的区别:

if(errorCode > 0)
{
   DisplayError(errorCode);
}
else
{
   // Do other stuff
}

else块将一直持续到函数结束,因此控制流基本上是相同的。这里是否存在性能差异,或者是否应该使用约定,或者这两种情况是否完全相同?

两种情况下生成的代码完全相同

在第一个示例中,您在代码周围缺少括号,但我将假定这是一个输入错误,您实际上是在询问使用return和else之间的区别

如果查看这两种方法的生成代码:

public static void Test1(int errorCode) {
  if (errorCode > 0) {
    Console.WriteLine(errorCode);
    return;
  }
  Console.WriteLine("ok");
}

public static void Test2(int errorCode) {
  if (errorCode > 0) {
    Console.WriteLine(errorCode);
  } else {
    Console.WriteLine("ok");
  }
}
它将如下所示:

if(errorCode > 0)
{
   DisplayError(errorCode);
   return;
}

// Continue to do stuff otherwise.
            if (errorCode > 0) {
011A00DA  in          al,dx  
011A00DB  push        eax  
011A00DC  mov         dword ptr [ebp-4],ecx  
011A00DF  cmp         dword ptr ds:[10F3178h],0  
011A00E6  je          011A00ED  
011A00E8  call        7470C310  
011A00ED  cmp         dword ptr [ebp-4],0  
011A00F1  jle         011A0100  
                Console.WriteLine(errorCode);
011A00F3  mov         ecx,dword ptr [ebp-4]  
011A00F6  call        73C5A920  
                return;
011A00FB  nop  
011A00FC  mov         esp,ebp  
011A00FE  pop         ebp  
011A00FF  ret  
            }
            Console.WriteLine("ok");
011A0100  mov         ecx,dword ptr ds:[3E92190h]  
011A0106  call        7359023C  
        }
011A010B  nop  
011A010C  mov         esp,ebp  
011A010E  pop         ebp  
011A010F  ret
以及:


生成的代码完全相同,一直到最后一条指令。

两种情况下生成的代码完全相同

在第一个示例中,您在代码周围缺少括号,但我将假定这是一个输入错误,您实际上是在询问使用return和else之间的区别

如果查看这两种方法的生成代码:

public static void Test1(int errorCode) {
  if (errorCode > 0) {
    Console.WriteLine(errorCode);
    return;
  }
  Console.WriteLine("ok");
}

public static void Test2(int errorCode) {
  if (errorCode > 0) {
    Console.WriteLine(errorCode);
  } else {
    Console.WriteLine("ok");
  }
}
它将如下所示:

if(errorCode > 0)
{
   DisplayError(errorCode);
   return;
}

// Continue to do stuff otherwise.
            if (errorCode > 0) {
011A00DA  in          al,dx  
011A00DB  push        eax  
011A00DC  mov         dword ptr [ebp-4],ecx  
011A00DF  cmp         dword ptr ds:[10F3178h],0  
011A00E6  je          011A00ED  
011A00E8  call        7470C310  
011A00ED  cmp         dword ptr [ebp-4],0  
011A00F1  jle         011A0100  
                Console.WriteLine(errorCode);
011A00F3  mov         ecx,dword ptr [ebp-4]  
011A00F6  call        73C5A920  
                return;
011A00FB  nop  
011A00FC  mov         esp,ebp  
011A00FE  pop         ebp  
011A00FF  ret  
            }
            Console.WriteLine("ok");
011A0100  mov         ecx,dword ptr ds:[3E92190h]  
011A0106  call        7359023C  
        }
011A010B  nop  
011A010C  mov         esp,ebp  
011A010E  pop         ebp  
011A010F  ret
以及:


生成的代码完全相同,一直到最后一条指令。

离题,但太大,无法发表评论,因为您还可以使用优秀的IL反汇编

有趣的是,仅在调试模式下分解IL时,Guffa的Test2 IL中还有几个额外的IL,根据Guffa的回答,这些IL在x86/x64 JIT中编译:

调试IL:


离题,但太大的评论,是你也可以使用优秀的IL反汇编

有趣的是,仅在调试模式下分解IL时,Guffa的Test2 IL中还有几个额外的IL,根据Guffa的回答,这些IL在x86/x64 JIT中编译:

调试IL:


还有一件更重要的事情需要注意,不管if语句的结果如何,都将执行return。它不是if块的一部分。尝试这种微优化几乎总是被误导的——宁愿选择可读的代码,而不是假设你比编译器更聪明。如果你需要压缩性能、度量和基准,那么就没有什么灵丹妙药了。提前返回通常是一种风格上的改进,而不是与性能相关的改进,因为它减少了嵌套。请看,鉴于您的第一个代码段包含似乎是逻辑错误的内容,我想说,很明显,第二个代码段更具可读性。@Habib您是对的。那是我的打字错误,不是我项目中的错误。这里没有逻辑问题,只是性能和/或约定的问题。需要注意的另一件重要的事情是,无论if语句的结果如何,都将执行return。它不是if块的一部分。尝试这种微优化几乎总是被误导的——宁愿选择可读的代码,而不是假设你比编译器更聪明。如果你需要压缩性能、度量和基准,那么就没有什么灵丹妙药了。提前返回通常是一种风格上的改进,而不是与性能相关的改进,因为它减少了嵌套。请看,鉴于您的第一个代码段包含似乎是逻辑错误的内容,我想说,很明显,第二个代码段更具可读性。@Habib您是对的。那是我的打字错误,不是我项目中的错误。我这里没有逻辑问题,只是性能和/或惯例的问题。哇,这真的很有帮助,同时也很有趣。介意我问你如何生成这样的代码吗?我对它没有任何经验。@McAdam331:在Visual Studio中,您可以在要检查和调试的代码上设置断点。当断点命中时,打开反汇编窗口ctrl+alt+D。请注意,在调试和发布模式下编译的代码是不同的;在调试模式下,可能会添加额外的nop指令用于调试目的,并且代码没有经过优化,在发布模式下,代码可以通过优化进行重新排列,因此可能与源代码不完全相似。哇,这真的很有帮助,同时也很有趣。介意我问你如何生成这样的代码吗?我对它没有任何经验。@McAdam331:在Visual Studio中,您可以在要检查和调试的代码上设置断点。当断点命中时,打开反汇编窗口ctrl+alt+D。请注意,在调试和发布模式下编译的代码是不同的;在调试模式下,可能会添加额外的nop指令以进行调试,并且代码未经过优化,在发布模式下,可以通过优化重新排列代码,使其可能与源代码不完全相似。是否在调试模式下编译?有额外的nop指令
是的,就是这样-在LinqPad中启用optimize+会删除nops+进行其他优化。IL变得相同。您是否在调试模式下编译?当您这样做时,会添加额外的nop指令。是的,就是这样-在LinqPad中启用optimize+,nops+会删除其他优化。IL变得相同。