在c#中使用switch语句和if/else语句的优缺点是什么?除了代码的外观,我无法想象有这么大的区别。

是否有任何原因导致最终的IL或相关的运行时性能会有根本的不同?

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


当前回答

我认为,不只是c#,而是所有基于C的语言:因为切换仅限于常量,所以使用“跳转表”可以生成非常高效的代码。C用例实际上是一个很好的老式FORTRAN计算GOTO,但c#用例仍然是针对常量进行测试。

优化器不可能生成相同的代码。考虑,例如,

if(a == 3){ //...
} else if (a == 5 || a == 7){ //...
} else {//...
}

因为这些是复合布尔值,生成的代码必须计算一个值,然后短路。现在考虑一下

switch(a){
   case 3: // ...
    break;
   case 5:
   case 7: //...
    break;
   default: //...
}

这可以编译成

BTABL: *
B3:   addr of 3 code
B5:
B7:   addr of 5,7 code
      load 0,1 ino reg X based on value
      jump indirect through BTABL+x

因为你隐式地告诉编译器它不需要计算OR和相等测试。

其他回答

实际上,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”代码的速度可以是基于开关的代码的两倍。即使编译器将“switch”转换为某种聪明的表驱动的goto,它仍然不会像简单地检查零那样快。

根据这个链接,使用Switch和IF语句的迭代测试的IF和Switch比较,就像对于1,000,000,000次迭代,Switch语句花费的时间= 44.3秒,IF语句花费的时间= 48.0秒

也就是每秒20833333次迭代,所以,我们真的需要更专注吗,

附注:只是为了了解在少量条件下的性能差异。

有三个理由支持这种转变:

A compiler targeting native code can often compile a switch statement into one conditional branch plus an indirect jump whereas a sequence of ifs requires a sequence of conditional branches. Depending on the density of cases a great many learned papers have been written about how to compile case statements efficiently; some are linked from the lcc compiler page. (Lcc had one of the more innovative compilers for switches.) A switch statement is a choice among mutually exclusive alternatives and the switch syntax makes this control flow more transparent to the programmer then a nest of if-then-else statements. In some languages, including definitely ML and Haskell, the compiler checks to see if you have left out any cases. I view this feature as one of the major advantages of ML and Haskell. I don't know if C# can do this.

一个趣闻:在托尼·霍尔接受终身成就奖的演讲中,我听到他说,在他职业生涯中所做的所有事情中,有三件事是他最自豪的:

发明快速排序 发明switch语句(Tony称之为case语句) 开始和结束他的工业生涯

我无法想象没有开关的生活。

如果你只使用If或else语句基解使用比较?操作符

(value == value1) ? (type1)do this : (type1)or do this;

你可以在开关中执行或程序

switch(typeCode)
{
   case TypeCode:Int32:
   case TypeCode.Int64:
     //dosomething here
     break;
   default: return;
}