这个问题主要针对C / C ++,但我猜其他语言也是相关的。
我无法理解为什么仍然使用switch / case而不是if / else if。在我看来,很像使用goto,并导致相同类型的混乱代码,而if / else如果以更有条理的方式可以实现相同的结果。
不过,我经常看到这些街区。找到它们的一个常见位置是在消息循环(WndProc ...)附近,而这些是它们引发最严重破坏的地方之一:变量在整个块中共享,即使不是主要的(也不是在里面初始化)。必须特别注意不要放弃休息,等等......
就个人而言,我避免使用它们,我想知道我错过了什么?
它们比if / else更有效吗? 它们是按照传统继承的吗?
答案 0 :(得分:159)
总结我的初始帖子和评论 - switch
语句优于if
/ else
语句有以下几个优点:
清洁代码。具有多个链式if
/ else if ...
的代码看起来很混乱,难以维护 - switch
使结构更清晰。
性能。对于密集case
值,编译器生成跳转表,用于稀疏 - 二进制搜索或一系列if
/ else
,因此在最坏的情况下switch
与if
一样快} / else
,但通常更快。虽然某些编译器可以类似地优化if
/ else
。
测试顺序无关紧要。为了加快一系列if
/ else
测试,需要首先考虑更多可能的案例。使用switch
/ case
程序员无需考虑这一点。
默认可以在任何地方。 if
/ else
默认情况必须在最后else
之后。 switch
- default
可以在任何地方,只要程序员发现它更合适。
常用代码。如果您需要针对多种情况执行公共代码,则可能会忽略break
并且执行将“失败” - 这是if
/ else
无法实现的。 (对于这种情况,有一个特殊的评论/* FALLTHROUGH */
是一种很好的做法--Lint识别它并且没有抱怨,如果没有这个评论,它会抱怨,因为忘记break
)是常见的错误。 / p>
感谢所有评论者。
答案 1 :(得分:31)
嗯,一个原因是清晰......
如果你有一个开关/案例,那么表达式不能改变.... 即。
switch (foo[bar][baz]) {
case 'a':
...
break;
case 'b':
...
break;
}
而if if / else,如果你错误地写(或意图):
if (foo[bar][baz] == 'a') {
....
}
else if (foo[bar][baz+1] == 'b') {
....
}
阅读你的代码的人会怀疑“foo表达式应该是相同的”,还是“为什么它们不同”?
答案 2 :(得分:16)
请记住,case / select提供了额外的灵活性:
以及执行得更快(通过跳转/查找表)*历史性
答案 3 :(得分:11)
还要记住,switch语句允许控制流继续,这允许您很好地组合条件,同时允许您为特定条件添加其他代码,例如在下面的代码中:
switch (dayOfWeek)
{
case MONDAY:
garfieldUnhappy = true;
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
weekDay = true;
break;
case SATURDAY:
weekendJustStarted = true;
case SUNDAY:
weekendDay = true;
break;
}
在这里使用if/else
语句不会有任何好处。
if (dayOfWeek == MONDAY)
{
garfieldUnhappy = true;
}
if (dayOfWeek == SATURDAY)
{
weekendJustStarted = true;
}
if (dayOfWeek == MONDAY || dayOfWeek == TUESDAY || dayOfWeek == WEDNESDAY
|| dayOfWeek == THURSDAY || dayOfWeek == FRIDAY)
{
weekDay = true;
}
else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY)
{
weekendDay = true;
}
答案 4 :(得分:9)
如果有很多情况,那么switch语句似乎更清晰。
当你有多个你想要相同行为的值时,这也很好 - 只使用多个“case”语句,这些语句落到单个实现中比if(这个||那个|| someotherthing |)更容易阅读。 | ...)
答案 5 :(得分:6)
它可能还取决于您的语言 - 例如,某些语言切换仅适用于数字类型,因此当您使用枚举值,数字常量等等时,它可以节省一些输入... < / p>
If (day == DAYOFWEEK_MONDAY) {
//...
}
else if (day == DAYOFWEEK_TUESDAY) {
//...
}
//etc...
或者稍微容易阅读...
switch (day) {
case DAYOFWEEK_MONDAY :
//...
case DAYOFWEEK_TUESDAY :
//...
//etc...
}
答案 6 :(得分:4)
开关/案例通常比if / else if / else更有效地进行优化,但偶尔(取决于语言和编译器)转换为简单的if / else if / else语句。
我个人认为switch语句使代码比一堆if语句更具可读性;只要遵循一些简单的规则即可。您甚至应该遵循if / else if / else情况的规则,但这也是我的意见。
这些规则:
答案 7 :(得分:4)
净度。正如我所说here,else if
有问题的线索是
ELSE IF的频率 以更加有限的方式使用 比语法所允许的。它是一个 灵活的大锤, 允许完全无关 要测试的条件。但它是 经常用来拍打苍蝇 CASE,比较相同的表达式 具有替代值......
这降低了可读性 码。由于结构允许 条件复杂性的宇宙, 读者需要保持更多 解析时的可能性 ELSE IF比解析CASE时。
答案 8 :(得分:4)
实际上,一个转换语句意味着你正在处理一个或多或少是枚举的东西,它会让你立即知道发生了什么。
也就是说,任何OO语言中枚举的开关都可以更好地编码 - 并且在相同的“枚举”样式值上的一系列if / else将至少同样糟糕,甚至更难以传达意义。
答案 9 :(得分:3)
解决了交换机内部所有内容都具有相同范围的问题,您可以随时将您的案例逻辑抛入另一个{}块,如此...
switch( thing ) {
case ONETHING: {
int x; // local to the case!
...
}
break;
case ANOTHERTHING: {
int x; // a different x than the other one
}
break;
}
..现在我不是说这很漂亮。如果您绝对不得不在一个案例中将某些案件与另一个案件隔离开来,那就把它作为可能的东西放在那里。
关于范围问题的另一个想法 - 将一个开关放在一个函数中而不是其他很多东西似乎是一个好习惯。在这种情况下,变量范围并不是一个值得关注的问题,因为通常情况下,您通常只处理任何给定函数调用的一个执行情况。
好的,关于开关的最后一个想法:如果一个函数包含多个开关,那么可能是重构代码的时候了。如果一个函数包含嵌套开关,它可能是一个重新思考你的设计的线索=)
答案 10 :(得分:1)
switch case主要用于在编程中做出选择。这与条件语句无关:
如果您的程序只需要选择,那么为什么使用if / else块并增加编程工作量,这会降低程序的执行速度。
答案 11 :(得分:0)
非常确定他们编译的内容与if
/ else if
相同,但当超过2或3时,我发现switch
/ case
更容易阅读else
秒。
答案 12 :(得分:0)
可以针对速度优化Switch语句,但是如果案例值分布在大量值上,则可以占用更多内存。
if / else通常很慢,因为需要检查每个值。
答案 13 :(得分:0)
Smalltalker可能会拒绝switch和if-then-else,并且可能会写出如下内容: -
shortToLongDaysMap := Dictionary new.
shortToLongDaysMap
at: 'Mon' put: 'Monday';
at: 'Tue' put: 'Tuesday';
at: 'Wed' put: 'Wednesday'
etc etc.
longForm := shortToLongDaysMap at: shortForm ifAbsent: [shortForm]
这是一个简单的例子,但我希望你能看到这种技术如何适用于大量案例。
注意at:IfAbsent:
的第二个参数类似于case语句的default子句。
答案 14 :(得分:0)
这背后的主要原因是可维护性和可读性。使用Switch / case语句然后if / else很容易使代码更易读和可维护。因为你有很多if / else然后代码变得像nest一样混乱,很难维护它。
还有一些执行时间是另一个原因。