在C#中使用if/else和switch-case之间是否有任何显着差异?

Mat*_*orn 209 .net c# switch-statement

在C#中使用switch语句与使用语句的好处/缺点是什么?if/else我无法想象除了你的代码外观之外还有其他重大差异.

是否有任何理由导致生成的IL或相关的运行时性能完全不同?

相关:什么是更快,打开字符串或elseif类型?

ima*_*ima 325

SWITCH语句仅在调试或兼容模式下生成与IF相同的程序集.在发布中,它将被编译成跳转表(通过MSIL'witch'语句) - 即O(1).

C#(与许多其他语言不同)也允许打开字符串常量 - 这有点不同.为任意长度的字符串构建跳转表显然是不切实际的,因此大多数情况下这样的开关将被编译成IF堆栈.

但是如果条件的数量足以覆盖开销,C#编译器将创建一个HashTable对象,用字符串常量填充它并在该表上进行查找,然后跳转.Hashtable查找不是严格的O(1)并且具有明显的恒定成本,但是如果案例标签的数量很大,则它将比与IF中的每个字符串常量相比明显更快.

总而言之,如果条件数大于5,则优先选择SWITCH,否则使用看起来更好的东西.

  • 一些实验表明,计数<= 6:"if"; count> = 7:字典.那就是MS .NET 3.5 C#编译器 - 它当然可以在版本和供应商之间进行更改. (46认同)
  • 嘿,我欠你一个道歉.抱歉是个骨头. (34认同)
  • 我想大约十个.20为安全起见.顺便说一下,我的愤怒不是你,而是人们的支持和接受. (7认同)
  • 你确定 C# 编译器会生成一个哈希表吗?我在上面的评论讨论中关于哈希表的观点是关于本机编译器,而不是 C# 编译器。C# 编译器使用什么阈值来生成哈希表? (2认同)
  • 我只是好奇 (2认同)
  • 作为后续,对于实际应用,大多数时候是否存在现实世界的差异?我发现 C# 中的 switch 语句很奇怪,它们的语法不太像其他任何东西,而且我发现它们使我的代码可读性较差,是否值得费心使用 switch 语句,或者我应该只使用 else if 进行编程并且只来如果我遇到性能瓶颈,是否要返回并替换它们? (2认同)

Sco*_*ski 52

通常(考虑所有语言和所有编译器),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'的帖子.

  • ima,如果有错误,请指出它们.斯科特很乐意纠正这个帖子.如果没有,那些已经达到纠正答案能力的人就会这样做.这是这样一个网站运作的唯一方式,而且看起来一般情况下它都有效.或者拿球回家:) (9认同)
  • 我所能做的只是为犯一个愚蠢的错误而道歉.相信我,我对此感到愚蠢.说真的,我认为这仍然是最好的答案.在本机编译器中,可以使用哈希表来实现跳转,因此这不是一些可怕的错误.我犯了一个错误. (6认同)
  • @ima如果您认为答案是客观错误的,那么将其编辑为正确.这就是每个人都可以编辑答案的原因. (4认同)
  • MSIL中有一个switch原语,c#语句通常会编译成类似C的查找.在某些情况下(目标平台,cl交换机等),交换机可能会在编译期间扩展为IF,但它只是一个后备兼容性度量. (3认同)
  • @Scott:我建议您编辑第二和第三段以明确说明"for strings".人们可能不会在底部阅读更新. (2认同)

Nor*_*sey 18

有三个理由更喜欢switch:

  • 针对本机代码的编译器通常可以将switch语句编译为一个条件分支加上间接跳转,ifs 序列需要一系列条件分支.根据案件的密度,已经写了很多关于如何有效地编写案例陈述的学术论文; 一些是从lcc编译器页面链接的.(Lcc拥有一个更具创新性的交换机编译器.)

  • switch语句是互斥备选方案中的一种选择,并且switch语法使得该控制流程对程序员更加透明,然后是if-then-else语句的嵌套.

  • 在某些语言中,包括绝对ML和Haskell,编译器会检查您是否遗漏了任何案例.我认为这个功能是ML和Haskell的主要优点之一.我不知道C#是否可以做到这一点.

一则轶事:在他获得终身成就奖的一次演讲中,我听到Tony Hoare说他在职业生涯中所做的一切,他最为自豪的有三件事:

  • 发明Quicksort
  • 发明switch语句(Tony称之为case语句)
  • 开始和结束他在工业界的职业生涯

无法想象没有生活switch.


小智 15

编译器将几乎所有的东西都优化到相同的代码中,只有很小的差异(Knuth,任何人?).

区别在于switch语句比十五个if else语句串起来更清晰.

朋友不要让朋友堆叠if-else语句.

  • "朋友不要让朋友堆叠if-else语句." 你应该做一个bumber sitcker :) (12认同)

kem*_*002 14

实际上,switch语句更有效.编译器会将它优化为一个查找表,其中if/else语句不能.缺点是switch语句不能与变量值一起使用.
你做不到:

switch(variable)
{
   case someVariable
   break;
   default:
   break;
}
Run Code Online (Sandbox Code Playgroud)

它一定要是

switch(variable)
{
  case CONSTANT_VALUE;
  break;
  default:
  break;
}
Run Code Online (Sandbox Code Playgroud)

  • 你有什么数字吗?我很好奇编译器如何通过 If/Else 优化 switch 语句 (2认同)

Mar*_*sey 12

我没有看到其他人提出(显而易见的?)这一点,即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
}
Run Code Online (Sandbox Code Playgroud)

VS

switch(x) {
  case 0: 
         // do one thing
         break;
  case 1: 
         // do the other thing
         break;
  case 2: 
         // do the third thing
         break;
}
Run Code Online (Sandbox Code Playgroud)

如果x在90%的时间内为零,则"if-else"代码的速度可以是基于交换机的代码的两倍.即使编译器将"开关"转换为某种聪明的表驱动goto,它仍然不会像检查零那样快.

  • 最初的问题(三年前!)刚问及if/else和switch之间的优缺点.这是一个例子.我亲眼看到这种优化在例程的运行时间上产生了显着的差异. (6认同)
  • 没有过早的优化!一般来说,如果你有不止一些情况并且它们与`switch`兼容,那么`switch`语句更好(更可读,有时更快).*如果你知道*一个案例更有可能,你可以把它拉出来形成一个`if`-`else`-`witch`结构和*如果它快得多*,你就把它留下来.(重复,如果需要.)IMO仍然相当可读.如果`switch`退化并变得太小,正则表达式替换将完成将其转换为`else if`链的大部分工作. (3认同)

gbj*_*anb 7

通常它会看起来更好 - 也就是说更容易理解发生了什么.考虑到性能优势最多只是极其微小,代码视图是最重要的区别.

因此,如果if/else看起来更好,请使用它,否则使用switch语句.


小智 5

根据此链接,使用 switch 和 if 语句进行迭代测试的IF 与 Switch比较,就像 1,000,000,000 次迭代,Switch语句所花费的时间 = 43.0s & If 语句= 48.0s

这实际上是每秒20833333 次迭代,所以,我们是否真的需要更加关注,

PS:只是为了了解一小部分条件下的性能差异。