Case和If Else If:哪个更有效率?

70

可能重复:
“else if”比“switch() case”快吗?
在Java中,if/else与switch相对性能如何?

我又开始边写代码边调试了...当调试器通过case语句时,它会立即跳转到与条件匹配的项,然而当相同的逻辑使用if/else指定时,它会遍历每个if语句,直到找到胜者。case语句更有效率,还是我的调试器只是优化了步骤?(不用担心语法/错误,我把它打在SO上,不知道它是否能编译,我只是想说明一个原则,我不想将它们作为整数处理,因为我模糊地记得case使用偏移量与整数)我使用C#,但我对所有编程语言都感兴趣。

switch(myObject.GetType()){

    case typeof(Car):
        //do something
        break;

    case typeof(Bike):
        //do something
        break;

    case typeof(Unicycle):
        //do something
        break;

    case default:
        break;
}

VS

   Type myType = myObject.GetType();

   if (myType == typeof(Car)){
            //do something
   }

   else if (myType == typeof(Bike)){
            //do something
   }

   else if (myType == typeof(Unicycle)){
            //do something
   }
   else{

   }

11
这远远不是与语言无关的问题,任何答案都会紧密地绑定在一种特定的语言上。 - skaffman
5
更不用提特定的编译器和编译器版本。 - Pascal Cuoq
1
顺便说一句,这个问题的真正答案是让它们都实现一个共同的接口/抽象方法,例如Vehicle#doSomething(),并且在具体实现中自身定义每个方法,这样你只需要使用myObject.doSomething()即可。 - BalusC
Php,如果/否则语句在解析方式上更快。 - David Hobs
如果你严格地想要将一个变量与可能值的列表进行匹配(超过2个),请使用switch。对于其他情况,请使用if else。这样,如果你看到一块switch语句,你就立刻知道代码的目的是什么。 - BigName
显示剩余3条评论
7个回答

104

似乎编译器在优化switch语句时比if语句更好。

编译器不知道你是否关心评估if语句的顺序,因此无法进行任何优化。您可能会在if语句中调用方法,影响变量。对于switch语句,它知道可以同时评估所有子句,并可以将它们放在最有效的顺序中。

下面是一个简短的比较:
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx


1
我不理解这部分内容:“你可以在if语句中调用方法,从而影响变量”。这怎么可能发生在if else里呢?我认为这是一样的。 - Castelmager
1
你可以使用 if (++i) { .... },但是在 switch case 语句中你不能这样做。 - Granada

8

调试器使其更简单,因为您不想逐步执行编译器创建的实际代码。

如果开关包含超过五个项目,则使用查找表或哈希表实现,否则使用if..else实现。

请参阅密切相关的问题“else if”是否比“switch() case”更快?

除了C#之外的其他语言当然会以不同的方式实现它,但是switch通常更有效率。


7
许多编程语言优化了switch语句,使其比标准的if-else if结构快得多,前提是情况是编译器常量。许多语言使用跳转表或索引分支表来优化switch语句。 分支表 维基百科对switch语句有很好的讨论。此外,这里 是关于C中switch优化的讨论。
需要注意的一点是,switch语句可能被滥用,并且根据情况,使用多态性可能比使用switch语句更可取。请参见这里 以获取示例。

0
我认为这只是调试器使它变得简单了。 请注意,case和"if列表"不是最终相同的。 case块通常以“break”结束,这是有原因的。当在汇编中分解时,case语句实际上看起来像这样。
if myObject.GetType() == type of Car
    GOTO START_CAR
else if myObject.GetType() == type of Bike
    GOTO START_BIKE

LABEL START_CAR
//do something car     
GOTO END

LABEL START_BIKE
//do something bike  
GOTO END

LABEL END

如果没有 break,那么 case 块中会缺少 "GOTO END" 语句,并且实际上如果您落在 "car" case 中,您将会运行两个部分。
//do something car     
//do something bike  
GOTO END

0

我相信因为case必须是常量值,所以switch语句执行的是类似于goto的操作,根据变量的值跳转到正确的case,而在if/then语句中,它必须评估每个表达式。


0

0

维基百科的Switch statement entry相当大且实际上相当不错。有趣的观点:

  • 开关语句本质上并不快。这取决于语言、编译器和具体用途。
  • 编译器可能使用跳转表或索引函数指针来优化开关语句。
  • 该语句的灵感来自于Stephen Kleene(以及其他人)的一些有趣的数学。

有关使用C开关语句的奇怪而有趣的优化,请参见Duff's Device


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