我正在试图找出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...!");
}
答案 0 :(得分:14)
首先,其他答案说(1)担心重要的事情,(2)以最好的方式编写代码,(3)如果你真的担心,测量它,是正确的。< / p>
所有人都说,重要的是要认识到只要保留了意义,编译器就可以以任何方式生成代码,并且编译器经常更改{{}中布尔值的“符号”。 1}}这样他们就可以生成更好的代码。请记住,当编译器将C#转换为IL,并且抖动将IL转换为机器代码时,将不会有if
语句。在IL中,只有“在堆栈上生成一个bool;如果bool为真/假则跳转”,或者“在寄存器中放置一个bool;如果寄存器为零/非零,则在机器代码中跳转”。
当你说:
if
编译器可以生成等效的这些指令:
if (A())
B();
C();
或者它可以很容易地生成:
call A()
if last result is false then goto SKIP
call B()
SKIP: call C()
请注意,第一个版本反转了测试符号,比第二个版本短一个指令,因此更有可能由试图保持代码短路的优化编译器生成。
在这种精神下,允许编译器选择比较相等而不是不等,并反转测试的符号,这样做会产生更好的代码。同样,C#编译器有时会将call A()
if last result is true then goto CONSEQUENCE
goto SKIP
CONSEQUENCE: call B()
SKIP: call C()
转换为if (A() <= B())
,反之亦然,这样做不会改变程序的含义,并且当一个版本比另一个版本短时。
我的观点是,从平等到不平等的转变可能在生成的代码中根本没有任何区别,因为编译器会自动将代码重写为更好的版本。相信编译器可以完成它的工作,并担心别的事情。
答案 1 :(得分:11)
我会说你应该以最可读的方式写它。这样的微优化根本不可能对您的代码产生任何可辨别的差异:您最多只讨论 每次比较一次“非”操作。如果它是一个显着的差异,那么编译器可能无论如何都会优化它,但实际上这甚至都没有想到。
答案 2 :(得分:2)
在普通处理器上,如果内存和速度相同,则跳跃如果相等且跳转如果不相等的指令非常相似。而且假设编译器没有优化语法差异。
答案 3 :(得分:2)
以为我会说我的话......
如果此代码已经在它自己的函数中,我只会执行检查,然后如果我不想执行其余的代码则返回。像这样:
void PointlessExample(){
string myString = "weekend";
if(myString != "weekend")
{
Console.WriteLine("No fun...!");
return;
}
//rest of the code
}
答案 4 :(得分:1)
我建议将高复杂度逻辑转换为单独的方法,从而抽象出逻辑,并简化方法。
string myString = "weekend";
if(myString == "weekend")
{
ComplexMethod();
}
else
{
Console.WriteLine("No fun...!");
}
这样你编写if语句的方式无关紧要。
就业绩而言,我认为您不会发现==
和!=
之间存在任何重大差异。
答案 5 :(得分:1)
由于性能没有真正的差异(如果你处于一个非常非常紧凑的循环中它只会真的很重要),我强烈建议不要在==或!=上“标准化”,而只是去做什么在这种情况下是有道理的。
我通常首先放置较小的案例,否则最终会在代码末尾添加许多悬挂括号。
e.g。
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")
}