6

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

示例(一个相当简单的示例,但总体思路成立):

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

如果我更改 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...!");
}
4

6 回答 6

17

首先,其他答案说(1)担心重要的事情,(2)以看起来最好的方式编写代码,以及(3)如果你真的担心,测量它,是正确的。

总而言之,重要的是要认识到,只要保留含义,编译器就可以以任何感觉的方式生成代码,并且编译器非常频繁地更改布尔值的“符号”,if以便它们可以生成更好的代码。请记住,当编译器将 C# 翻译成 IL,而 jitter 将 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# 编译器有时会变成if (A() <= B())这样if (!(A() > B()),反之亦然,这样做不会改变程序的含义,并且当一个版本比另一个版本短时。

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

于 2013-06-21T15:15:20.857 回答
13

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

于 2013-06-21T13:49:41.037 回答
2

在普通处理器上,jump-if-equal 和 jump-if-not-equal 指令在内存和速度方面非常相似。这是假设编译器没有优化语法差异。

于 2013-06-21T13:48:22.703 回答
2

只是以为我会发表意见......

如果此代码已经在它自己的函数中,我将只执行检查,然后如果我不想执行其余代码则返回。像这样的东西:

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

    //rest of the code
}
于 2013-06-21T15:11:37.863 回答
1

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

string myString = "weekend";
if(myString == "weekend")
{        
    ComplexMethod();
}
else
{
    Console.WriteLine("No fun...!");
}

这样,您编写 if 语句的方式无关紧要。


在性能方面,我认为您不会发现==和之间有任何显着差异!=

于 2013-06-21T13:49:39.757 回答
1

由于在性能上没有真正的区别(而且只有在非常紧凑的循环中才真正重要),我强烈建议不要在 == 或 != 上“标准化”,而是只使用有意义的东西情况。

我通常将较小的情况放在首位,否则您的代码末尾会出现很多挂括号。

例如

if (number != 1337) 
{
    Console.Writeline("Nope")
}
else 
{
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
    // Do lots of stuff
}

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")
}
于 2013-06-21T13:53:30.993 回答