布尔语法的性能和优雅问题



这个问题更多的是性能问题,而不是优雅,我为自己说话,但。。。

两个选项都可以实现,这对cpu来说计算速度更快,或者如果最后它是相同的(我倾向于认为是的,因为条件是(x<10)相同)

    public int DidLogcount = 0; // DidLogCount is raised by +1 every time we deside, then condition is met 
    public bool MoreLogsAllowed()
    {
        if (DidLogcount < 10) return true;
        else return false;
    }

    public bool MoreLogsAllowed()
    {
       return DidLogcount < 10;
    }

我们大多数时候都假设检查它是否为null,但如果必须的话,它将包括这两种情况,所以我想我只是缩小了范围(?),如果我没有遗漏任何其他问题的话。

我会通知你正确的答案。thx。

重新筛选:我只是想标记正确的答案,但刷新了页面,页面上又加载了3个。。。

等待更多的投票。。。现在,我真的要感谢大家!为了分享你的知识,我确实想到了编译器的优化问题,所以……打印出来的结果显示了一些东西,尽管微小的差异本身就很小,但当添加到一堆条件中时,它就不那么小了,除非我们谈论的是一个真正复杂的应用程序,否则我不会说它很大。性能问题,连同逻辑性和可读性,从来都不是一个小问题感谢@Steve&尼克真的为我们测试了一下。

我不确定是否会有任何性能差异,如果有,则可以忽略不计。但第二种情况更优雅。

使用LinqPAD进行测试。

int DidLogcount = 5;
void Main()
{
    MoreLogsAllowed();
    MoreLogsAllowed2();
}
public bool MoreLogsAllowed() 
{ 
    if (DidLogcount < 10) return true; 
    else return false; 
} 
public bool MoreLogsAllowed2() 
{ 
    return (DidLogcount < 10); 
} 

并产生这个IL代码

IL_0000:  ldarg.0     
IL_0001:  call        UserQuery.MoreLogsAllowed
IL_0006:  pop         
IL_0007:  ldarg.0     
IL_0008:  call        UserQuery.MoreLogsAllowed2
MoreLogsAllowed:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery.DidLogcount
IL_0006:  ldc.i4.s    0A 
IL_0008:  bge.s       IL_000C
IL_000A:  ldc.i4.1    
IL_000B:  ret         
IL_000C:  ldc.i4.0    
IL_000D:  ret         
MoreLogsAllowed2:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery.DidLogcount
IL_0006:  ldc.i4.s    0A 
IL_0008:  clt         
IL_000A:  ret    

第二个版本不仅更优雅,而且似乎生成了更短的代码
为了确保这不是LinqPAD引入的差异,我用Visual Studio 2010创建了一个小型控制台应用程序,并在发布模式下使用默认设置进行编译
然后我用ILDASM查看IL colde
我确认上面的代码与编译器生成的代码相同
当然,差异可以忽略不计,但这两个版本不会产生相同的IL代码。

对我来说,第一个例子并不优雅。而且我认为编译器会优化第一个例子,所以性能没什么好说的。对我来说,第二个例子更简洁、更短、可读性更强。

如果这两种选择的性能有差异,我会感到非常惊讶。我也觉得第二种选择更优雅,我甚至会省略括号。

然而,在更复杂的条件下,尤其是涉及函数调用的情况下,将两个返回语句放在不同的行上,可以更方便地在使用调试器遍历代码时了解发生了什么。

任何性能差异都可能可以忽略不计,并且高度依赖于.NET JIT编译的结果,但在x86示例中,比较结果为:

                if (DidLogcount < 10) return true;
... skipped DidLogCount call...
    00000020  mov         dword ptr [ebp-4],eax 
    00000023  cmp         dword ptr [ebp-4],0Ah 
    00000027  jge         00000037 
    00000029  mov         eax,1 
    0000002e  and         eax,0FFh 
    00000033  mov         esp,ebp 
    00000035  pop         ebp 
    00000036  ret 
                else return false;
    00000037  xor         eax,eax 
    00000039  mov         esp,ebp 
    0000003b  pop         ebp 
    0000003c  ret 

            return (DidLogcount < 10);
    ... skipped DidLogCount call...
0000001f  mov         dword ptr [ebp-4],eax 
00000022  cmp         dword ptr [ebp-4],0Ah 
00000026  setl        al 
00000029  movzx       eax,al 
0000002c  mov         esp,ebp 
0000002e  pop         ebp 
0000002f  ret 

后者可能会稍微快一点,但这也取决于你的CPU是如何处理这些指令的。

最好的答案是编写一个测试应用程序来测量它!

两个片段之间没有区别,因为最重要的是MSIL,在编译之后,在这种情况下,编译的代码是相同的。

Code 1 C# -> MSIL 1 -> Code natif 1
Code 2 C# -> MSIL 1 -> Code natif 1

最新更新