为什么我们使用if,否则如果代替多个block,如果主体是return语句
我总是习惯使用if,else-if语句而不是多个if语句。
例:
int val = -1; if (a == b1) { return c1; } else if (a == b2) { return c2; } ... ... } else { return c11; }
它与例2相比如何:
if (a == b1) { return c1; } if (a == b2) { return c2; } .... if (a == b11) { return c11; }
我知道function明智,他们是一样的。 但是,如果还有其他问题,最好还是做一下呢? 这是我的朋友提出的,当我指出他可以构build不同的代码库,使其更加清洁。 这对我来说已经是一种习惯,但我从来没有问过为什么。
if-elseif-else
语句只要find一个真的就停止比较。 if-if-if
每一个比较。 第一个更有效率。
编辑:它已经在评论中指出,你在每个if
块做一个return
。 在这些情况下,或者在控制将离开方法的情况下(例外情况),在执行多个if
语句和执行if-elseif-else
语句之间没有区别。
但是,最好的做法是使用if-elseif-else
。 假设你改变你的代码,这样你就不会在每个if
块中做一个return
。 然后,为了保持效率,你还必须改变为一个if-elseif-else
成语。 if-elseif-else
从if-elseif-else
开始,可以节省您编辑的时间,而且对于阅读您的代码的人来说更加清晰(见证我刚刚给您的代码做了简略的解释!)。
那么b1 == b2
的情况呢? (如果a == b1
和a == b2
?)
发生这种情况时,一般来说,以下两个代码块可能会有不同的行为:
if (a == b1) { /* do stuff here, and break out of the test */ } else if (a == b2) { /* this block is never reached */ }
和:
if (a == b1) { /* do stuff here */ } if (a == b2) { /* do this stuff, as well */ }
如果您想清楚描述不同情况下的function,请使用if-else
或switch-case
进行一项testing 。
如果您需要多种情况下的不同function,则可以使用多个块作为单独的testing 。
这不是“最佳实践”的问题,而是定义您是否有一个testing或多个testing。
在function上不等同。
唯一的方法是在function上等价的是,如果你为每一个可能的值做一个“if”语句(例如:每个可能的int值,如C语言的limits.h中定义的;使用INT_MIN和INT_MAX或者Java )。
else语句允许您覆盖每个可能的剩余值,而不必编写数百万个“if”语句。
另外,使用if … else if … else更好的编码习惯,就像在switch / case语句中一样,如果不提供“默认”case语句,编译器会给你一个警告。 这可以防止您忽略程序中的无效值。 例如:
double square_root(double x) { if(x > 0.0f) { return sqrt(x); } else if(x == 0.0f) { return x; } else { printf("INVALID VALUE: x must be greater than zero"); return 0.0f; } }
在这种情况下,你是否要为每个可能的x值input数百万条if语句? 对此感到怀疑 :)
干杯!
我倾向于认为使用else if
更容易在代码更改的情况下更健壮。 如果有人要调整函数的控制stream,用try-catch
代替带有副作用或函数调用的返回, else-if
如果所有的条件都是真正的独占,那么else-if
会失败。 这实际上取决于您正在使用的确切代码来作出一般性判断,您需要考虑可能的权衡以简洁。
在每个if
分支中都有return
语句。
在你的代码中,你在每个if条件中都有return
语句。 当你有这样的情况时,有两种方法来写这个。 首先是你如何写在例1中:
if (a == b1) { return c1; } else if (a == b2) { return c2; } else { return c11; }
另一个是如下:
if (a == b1) { return c1; } if (a == b2) { return c2; } return c11; // no if or else around this return statement
这两种编写代码的方式是相同的。
在例2中编写代码的方式不会在C ++或Java中编译(并且在C中是未定义的行为),因为编译器不知道你已经覆盖了所有可能的值,所以它认为有一个代码通过函数的path,可以让你到函数的结尾而不返回一个返回值。
if (a == b1) { return c1; } if (a == b2) { return c2; } ... if (a == b11) { return c11; } // what if you set a to some value c12?
没有return
语句在每个分支。
如果没有在每个分支中使用return
语句,只有在以下语句为真的情况下,您的代码在function上才是相同的:
- 你不要改变任何
a
分支的值。 -
==
是等价关系(在math意义上)并且b1
到b11
都不在相同的等价类中。 -
==
没有任何副作用。
为了进一步澄清第二点(还有第三点):
-
==
总是C或Java中的等价关系,永远不会有副作用。 - 在允许您重写
==
运算符(如C ++,Ruby或Scala)的语言中,重写的==
运算符可能不是等价关系,并且可能有副作用。 我们当然希望任何覆盖==
运算符的人都能够写出一个没有副作用的等价关系,但是不能保证。 - 在JavaScript和某些其他具有松散types转换规则的编程语言中,有些情况下内置于
==
不是传递的或不对称的语言中。 (在Javascript中,===
是等价关系。)
在性能方面,示例#1保证不会在匹配之后执行任何比较。 编译器可能会优化#2来跳过额外的比较,但这不太可能。 在下面的例子中,它可能不能,如果string很长,额外的比较并不便宜。
if (strcmp(str, "b1") == 0) { ... } if (strcmp(str, "b2") == 0) { ... } if (strcmp(str, "b3") == 0) { ... }
我更喜欢if / else结构,因为在每个变体中与开关一起评估问题的所有可能状态要容易得多。 我发现它更加稳健,debugging更快,特别是在弱types环境(如PHP)中执行多个布尔值评估时,为什么elseif不好(夸大了演示):
if(a && (c == d)) { } elseif ( b && (!d || a)) { } elseif ( d == a && ( b^2 > c)) { } else { }
这个问题已经超出了4 ^ 2 = 16个布尔状态,这只是为了演示弱分类效应,使事情变得更糟。 想象一下三个状态variables,三个variables问题, if ab elseif bc
不是另一种types的方式,就不难想象。
将优化留给编译器。
if
和else if
不同,连续两个if
语句。 在第一个,如果CPU采取第一个分支, else if
不会被检查。 在连续的两个if
语句中,即使第一个if
被检查,下一个if
也将被检查,如果条件为真。
我认为这些代码片段是相当的,因为你有很多return
语句。 如果你有一个单一的return
语句,你会使用else
构造,这是不必要的。
您的比较依赖于if语句的主体从方法返回控制的事实。 否则,function会有所不同。
在这种情况下,他们执行相同的function。 后者在我看来更容易阅读和理解,并将作为我的select使用。
他们可能做不同的事情。
如果a
等于b1
和b2
,则input两个if
块。 在第一个例子中,你只能input一个。 我想象的第一个例子是更快,因为编译器可能不得不顺序检查每个条件,因为某些比较规则可能适用于该对象。 它可能能够优化它们…但是如果你只想要一个被input,第一种方法更明显,不太可能导致开发人员的错误或代码效率低下,所以我肯定会推荐。
CanSpice的答案是正确的。 性能的另一个考虑是找出最经常发生的条件。 例如,如果a == b1只出现1%的时间,那么通过首先检查另一个案例可以获得更好的性能。
吉尔爱炸玉米饼的答案也不错。 最佳做法是确保您涵盖所有案例。