C# 执行速度:相等(=)与不相等(!=)

C# 执行速度:相等(=)与不相等(!=),c#,optimization,if-statement,C#,Optimization,If Statement,我试图找出一些if语句的最佳实践。当我需要打开某个等式,即需要if-else构造时,我通常在“not-equal”上写条件。这背后的原因是,通常当出现不成功的结果时,指令的数量和复杂性都很低。比较过程有什么不同吗?相等(=)和不相等(!=)之间的执行时间是否有差异 示例(一个相当简单的示例,但总体思路是正确的): 如果我更改if-else语句的顺序,执行时间是否有任何差异 string myString = "weekend"; if(myString == "weekend") {

我试图找出一些if语句的最佳实践。当我需要打开某个等式,即需要if-else构造时,我通常在“not-equal”上写条件。这背后的原因是,通常当出现不成功的结果时,指令的数量和复杂性都很低。比较过程有什么不同吗?相等(=)和不相等(!=)之间的执行时间是否有差异

示例(一个相当简单的示例,但总体思路是正确的):

如果我更改if-else语句的顺序,执行时间是否有任何差异

string myString = "weekend";
if(myString == "weekend")
{        
    //do a bunch of fun stuff with relatively high complexity
    //can expand over many lines of code
}
else
{
    Console.WriteLine("No fun...!");
}

在普通处理器上,相等跳转指令和不相等跳转指令在内存和速度方面非常相似。这是假设编译器没有优化语法上的差异。

我建议将您的高复杂性逻辑转移到一个单独的方法中,从而抽象逻辑,简化方法

string myString = "weekend";
if(myString == "weekend")
{        
    ComplexMethod();
}
else
{
    Console.WriteLine("No fun...!");
}
那样的话,你写if语句的方式就不重要了



就性能而言,我认为您不会发现
==
之间有任何显著差异=

我认为您应该以最具可读性的方式编写它。这样的微观优化不太可能对代码产生任何明显的影响:每次比较最多只需要一个“非”操作。如果这是一个显著的差异,那么编译器可能会对其进行优化,但实际上这根本不需要考虑。

因为在性能上没有真正的差异(而且只有在非常紧密的循环中才会真正起作用),我强烈建议不要对==或!=“标准化”,但是,在这种情况下,我们只需要做有意义的事情

我通常会先放一个小盒子,否则代码末尾会有很多挂括号

e、 g

相对于

if (number == 1337) 
{
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
}
else 
{
    Console.Writeline("Nope")
}
有些人更喜欢把动作放在第一位,把边缘放在第二位(说这更像是try{}catch{}),所以这更多的是风格问题,而不是最佳实践

<>如果很多东西都变得笨拙了,那么你可能想考虑把它包装在一个函数中,这意味着你输入的条目

不重要。
if (number == 1337) 
{
     DoLotsOfStuff();
}
else 
{
    Console.Writeline("Nope")
}

我只是想我会说

如果这段代码已经在它自己的函数中,我只需要执行检查,如果不想执行其余的代码,就返回。大概是这样的:

void PointlessExample(){
    string myString = "weekend";
    if(myString != "weekend")
    {
        Console.WriteLine("No fun...!");
        return;
    }

    //rest of the code
}

首先,其他回答是(1)担心重要的事情,(2)以最合适的方式编写代码,以及(3)如果你真的担心,请测量它,这是正确的

总而言之,重要的是要认识到,只要保留了代码的含义,编译器就可以以任何方式生成您的代码,并且编译器经常更改
if
中布尔值的“符号”,以便生成更好的代码。请记住,当编译器将C#转换为IL,而抖动将IL转换为机器代码时,将不会有
if
语句。IL中只有“在堆栈上生成布尔值;如果布尔值为真/假,则立即跳转”或机器代码中的“将布尔值放入寄存器;如果寄存器为零/非零,则立即跳转”

当你说:

if (A())  
    B();
C();
编译器可以生成这些指令的等效项:

call A()
if last result is false then goto SKIP
call B()
SKIP: call C()
或者它也可以很容易地生成:

call A()
if last result is true then goto CONSEQUENCE
goto SKIP
CONSEQUENCE: call B()
SKIP: call C()
请注意,第一个版本(反转测试符号)比第二个版本短一条指令,因此更可能由试图保持代码简短的优化编译器生成

本着这种精神,编译器可以选择比较等式而不是不等式,并在这样做生成更好的代码时反转测试符号。同样,C#编译器有时会在(A()B())
时打开
,反之亦然,因为这样做不会改变程序的含义,并且一个版本比另一个版本短


我的观点是,从相等改为不等可能不会对生成的代码产生任何影响,因为编译器会自动将代码重写为更好的版本。信任编译器完成它的工作,并担心其他事情。

尝试对其进行基准测试。我相信你会发现
=
在性能方面只是有点像
==
(所以它其实并不重要)。之后修复性能问题,这不太可能是一个问题。回答不错,关注代码结构而不是(过度)优化。编译器是否允许对用户定义的运算符重载进行此类优化?没有什么能阻止一个愚蠢的程序员拥有==和!==的非对称重载,这意味着这样的优化将改变程序的输出。@布赖恩:你似乎很好地回答了你自己的问题。这应该是可以接受的答案,因为它详细说明了在微优化方面信任编译器。
call A()
if last result is false then goto SKIP
call B()
SKIP: call C()
call A()
if last result is true then goto CONSEQUENCE
goto SKIP
CONSEQUENCE: call B()
SKIP: call C()