何时使用if-else if-else语句而不是switch语句,反之亦然

113
为什么要使用switch块而不是一系列的if语句?switch语句看起来做同样的事情,但需要输入更多字符。
10个回答

103

通常情况下,你应该根据上下文和概念上的正确方式来选择使用哪种语句。switch 语句实际上是在基于一个变量的值选择一个分支,而 if 语句只是一系列布尔检查。

举个例子,如果你要进行以下操作:

int value = // some value
if (value == 1) {
    doThis();
} else if (value == 2) {
    doThat();
} else {
    doTheOther();
}

如果使用 switch ,就更好地表达了基于“value”值而非任意测试进行操作选择的意图,这样会更加直观明了。

另外,如果你在使用面向对象编程语言时发现自己写了许多switch和if-else语句,那么应该考虑是否可以通过多态性来实现相同的结果。

最后,关于使用switch需要输入更多字符的问题,我不记得是谁说过了,但我曾经读到过有人问过:“你的打字速度真的会影响你编码的速度吗?”(意译)


5
可以使用枚举类型来代替随意的整数值,这样做可以使其更易读(并且在开关语句中也很好看)。 - WestDiscGolf
2
枚举类型在 PHP 中不是本地支持的,但可以通过类似于此主题中所示的方式进行“黑客式”添加:https://dev59.com/pnVC5IYBdhLWcg3wjx5d - CTS_AE
1
+1 如果提到了多态性。 - anar khalilov
毫无疑问,获胜的论点是:“很明显,选择行动是基于“value”的值而不是任意测试。” - Adrian Moisa
你应该考虑摆脱它们并使用多态性。为什么呢? - Diego

61

如果你要根据单个变量的值进行切换,那么每次都应使用switch语句,因为它就是为此而生的。

否则,请坚持使用多个if-else语句。


8
这确实是一个非常简单但全面的答案。 - anar khalilov

19

关于可读性:

我通常更喜欢在允许穿透的语言中使用if/else结构,而不是switch语句。我发现,随着项目的发展,多个开发人员参与后,构建switch语句会变得困难。

如果它们(语句)变得不再简单,许多程序员会变得懒惰,他们不会阅读整个语句以理解它,而会直接添加一个case来覆盖他们正在添加到语句中的任何情况。

我看过很多情况下,代码在switch语句中重复,因为某个人的测试已经被覆盖了,一个简单的fall-though case就足够了,但懒惰迫使他们在最后添加冗余代码,而不是尝试理解switch。我还看过一些噩梦般的switch语句,有许多糟糕构建的case,试图跟踪所有逻辑非常困难,还有许多分散的fall-through case和未被覆盖的case...这在某种程度上也导致了我谈到的第一个/冗余问题。

理论上,if/else结构可能存在相同的问题,但实际上这种情况似乎不太经常发生。也许(只是猜测)程序员必须更仔细地阅读if/else结构中通常更复杂的条件,因此需要更仔细地阅读?如果您正在编写某些简单的东西,并且知道其他人可能永远不会碰它,并且您可以良好地构建它,则我认为这是一种权衡。在这种情况下,无论哪种方式更易读且感觉最好,都可能是正确的答案,因为您可能会维护那段代码。

关于速度:

Switch语句通常比if-else结构执行得更快(但并非总是如此)。由于switch语句的可能值是预先布置的,编译器能够通过构建跳转表来优化性能。与if-else结构不同,每个条件不必被测试(直到找到正确的条件为止)。

然而,这并非总是如此。例如,如果你有一个简单的开关,它的可能值为1到10,那么情况就会如此。当你添加更多的值时,需要使用更大的跳转表,因此开关变得不那么高效(虽然比if/else语句低效,但比相对简单的开关语句也要低效)。同样,如果这些值高度不同(例如,你拥有10个可能值,如1、1000、10000、100000等,一直到100000000000),那么开关比较简单的情况下也更加低效。

希望这可以帮助你。


你(或其他人)能否详细说明一下你的第二条评论?为什么具有非连续值会很重要? - Frederick
2
@Frederick 当使用跳转表时,表中所需的条目数取决于最低和最高 case 值之间的差异:必须有 high - low + 1 条目。如果您有 case 0case 1case 100,则表中必须有 101 个条目,尽管只有三个 case 语句。由于表中的每个条目都会增加编译方法的大小,因此在您的 case 值稀疏分布时使用查找表是没有意义的。查找表更适用于密集分布。 - Mike Strobel

2

毫无疑问,switch语句更易于阅读和维护。而且通常更快速、更少出错。


1

在单个变量上有超过2个条件时,每次使用switch语句。以工作日为例,如果您对每个工作日都有不同的操作,则应使用switch语句。

其他情况(多个变量或复杂的if子句),您应该使用Ifs,但没有规定在哪里使用每个。


1
每当你有超过2个条件时,就应该使用switch语句,并且你应该在一个单独的变量上添加条件。 - Mehrdad Afshari
同意,这确实有很大的区别 :) - annakata
它只是让人们更清楚地了解在switch语句中只能使用一个条件。 - Sergio

0
避免因打字时间长而回避某些内容是不好的,应该努力消除这种倾向。但是,过于冗长的内容也很难阅读,因此简洁和简单非常重要,但重要的是易读性而不是可写性。简洁的一行代码经常比一个简单清晰的三四行代码更难读懂。
使用最适合描述操作逻辑的结构。

0

我个人更喜欢看到 switch 语句而不是太多嵌套的 if-else,因为它们更容易阅读。在显示状态方面,switches 在可读性方面也更好。

此帖子中还请参见有关 pacman ifs 的评论。


0
假设您已决定使用switch,因为您只在单个变量上工作,该变量可以具有不同的值。如果这会导致一个小的switch语句(2-3个case),那么我认为这是可以接受的。如果似乎您最终会得到更多的话,我建议改用多态性。在此处可以使用AbstractFactory模式创建一个对象,该对象将执行您尝试在switch中执行的任何操作。丑陋的switch语句将被抽象化,并且您最终将获得更清晰的代码。

0
这非常取决于具体情况。如果有许多嵌套的if-else,最好使用switch而不是if-else。
问题是什么程度算是“许多”?
昨天我也在问自己同样的问题:
public enum ProgramType {
    NEW, OLD
}

if (progType == OLD) {
    // ...
} else if (progType == NEW) {
    // ...
}

if (progType == OLD) {
    // ...
} else {
    // ...
}

switch (progType) {
case OLD:
    // ...
    break;
case NEW:
    // ...
    break;
default:
    break;
}

在此情况下,第一个if存在不必要的第二个测试。第二个感觉有一点糟糕,因为它隐藏了NEW。
最终我选择了switch,因为它更易读。

0

我经常认为,如果语言允许的话,使用elseif和通过case实例()是代码气味,如果不是味道。

对于我自己来说,我通常发现嵌套的(if / then / else)通常比elseif更好地反映了事物,并且对于互斥的情况(通常是其中一种属性组合优先于另一种情况),case或类似的东西更清晰易读两年后。

我认为Rexx使用的select语句是如何很好地执行“Case”的一个特别好的例子(没有drop-throughs)(愚蠢的例子):

Select
    When (Vehicle ¬= "Car") Then
        Name = "Red Bus"
    When (Colour == "Red") Then
        Name = "Ferrari"
    Otherwise
        Name = "Plain old other car"
    End

如果优化不够好,就换一个新的编译器或语言...


但是,如果在允许穿透的语言中使用switch语句,则比使用冗余代码更好。假设您有一个测试天数的开关,并且您希望在3天(星期一、三、五)发生相同的事情,您不希望列出相同的代码3次。最好使用穿透或if / else。 - Allen Ratcliff
哦,我不知道在新编译器中有更好的开关优化。你有例子吗?谢谢。 - Allen Ratcliff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接