在C#中使用switch
语句与使用语句的好处/缺点是什么?if/else
我无法想象除了你的代码外观之外还有其他重大差异.
是否有任何理由导致生成的IL或相关的运行时性能完全不同?
ima.. 325
SWITCH语句仅在调试或兼容模式下生成与IF相同的程序集.在发布中,它将被编译成跳转表(通过MSIL'witch'语句) - 即O(1).
C#(与许多其他语言不同)也允许打开字符串常量 - 这有点不同.为任意长度的字符串构建跳转表显然是不切实际的,因此大多数情况下这样的开关将被编译成IF堆栈.
但是如果条件的数量足以覆盖开销,C#编译器将创建一个HashTable对象,用字符串常量填充它并在该表上进行查找,然后跳转.Hashtable查找不是严格的O(1)并且具有明显的恒定成本,但是如果案例标签的数量很大,则它将比与IF中的每个字符串常量相比明显更快.
总而言之,如果条件数大于5,则优先选择SWITCH,否则使用看起来更好的东西.
SWITCH语句仅在调试或兼容模式下生成与IF相同的程序集.在发布中,它将被编译成跳转表(通过MSIL'witch'语句) - 即O(1).
C#(与许多其他语言不同)也允许打开字符串常量 - 这有点不同.为任意长度的字符串构建跳转表显然是不切实际的,因此大多数情况下这样的开关将被编译成IF堆栈.
但是如果条件的数量足以覆盖开销,C#编译器将创建一个HashTable对象,用字符串常量填充它并在该表上进行查找,然后跳转.Hashtable查找不是严格的O(1)并且具有明显的恒定成本,但是如果案例标签的数量很大,则它将比与IF中的每个字符串常量相比明显更快.
总而言之,如果条件数大于5,则优先选择SWITCH,否则使用看起来更好的东西.
通常(考虑所有语言和所有编译器),switch语句CAN SOMETIMES比if/else语句更有效,因为编译器很容易从switch语句生成跳转表.在给定适当约束的情况下,可以对if/else语句执行相同的操作,但这要困难得多.
在C#的情况下,这也是正确的,但出于其他原因.
使用大量字符串时,使用switch语句具有显着的性能优势,因为编译器将使用哈希表来实现跳转.
使用少量字符串,两者之间的性能是相同的.
这是因为在这种情况下,C#编译器不会生成跳转表.相反,它生成的MSIL等同于IF/ELSE块.
有一个"switch语句"MSIL指令,当jitted将使用跳转表来实现switch语句.它只适用于整数类型(但这个问题询问字符串).
对于少量字符串,编译器生成IF/ELSE块更有效,然后使用哈希表.
当我最初注意到这一点时,我假设因为IF/ELSE块与少量字符串一起使用,编译器对大量字符串进行了相同的转换.
这是错的.'IMA'非常友好地指出了这一点(嗯......他对此不好,但他是对的,我错了,这是重要的部分)
我还对MSIL中缺少"切换"指令做了一个假设(我想,如果有一个切换原语,为什么他们不使用哈希表,所以一定不能有切换原语. ......)这既错了,又让我非常愚蠢.再次'IMA'向我指出了这一点.
我在这里做了更新,因为它是评分最高的帖子,也是接受的答案.
但是,我已经把它作为社区Wiki,因为我觉得我不配错了REP.如果你有机会,请投票'ima'的帖子.
有三个理由更喜欢switch
:
针对本机代码的编译器通常可以将switch语句编译为一个条件分支加上间接跳转,而if
s 序列需要一系列条件分支.根据案件的密度,已经写了很多关于如何有效地编写案例陈述的学术论文; 一些是从lcc编译器页面链接的.(Lcc拥有一个更具创新性的交换机编译器.)
switch语句是互斥备选方案中的一种选择,并且switch语法使得该控制流程对程序员更加透明,然后是if-then-else语句的嵌套.
在某些语言中,包括绝对ML和Haskell,编译器会检查您是否遗漏了任何案例.我认为这个功能是ML和Haskell的主要优点之一.我不知道C#是否可以做到这一点.
一则轶事:在他获得终身成就奖的一次演讲中,我听到Tony Hoare说他在职业生涯中所做的一切,他最为自豪的有三件事:
发明Quicksort
发明switch语句(Tony称之为case
语句)
开始和结束他在工业界的职业生涯
我无法想象没有生活switch
.
编译器将几乎所有的东西都优化到相同的代码中,只有很小的差异(Knuth,任何人?).
区别在于switch语句比十五个if else语句串起来更清晰.
朋友不要让朋友堆叠if-else语句.
实际上,switch语句更有效.编译器会将它优化为一个查找表,其中if/else语句不能.缺点是switch语句不能与变量值一起使用.
你做不到:
switch(variable) { case someVariable break; default: break; }
它一定要是
switch(variable) { case CONSTANT_VALUE; break; default: break; }
我没有看到其他人提出(显而易见的?)这一点,即switch语句的假设效率优势取决于各种情况大致相同.在一个(或几个)值更可能的情况下,if-then-else梯形图可以更快,通过确保首先检查最常见的情况:
所以,例如:
if (x==0) then { // do one thing } else if (x==1) { // do the other thing } else if (x==2) { // do the third thing }
VS
switch(x) { case 0: // do one thing break; case 1: // do the other thing break; case 2: // do the third thing break; }
如果x在90%的时间内为零,则"if-else"代码的速度可以是基于交换机的代码的两倍.即使编译器将"开关"转换为某种聪明的表驱动goto,它仍然不会像检查零那样快.
通常它会看起来更好 - 也就是说更容易理解发生了什么.考虑到性能优势最多只是极其微小,代码视图是最重要的区别.
因此,如果if/else看起来更好,请使用它,否则使用switch语句.