"else if"是否比"switch()case"更快?

Iva*_*nov 344 c# performance if-statement switch-statement

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

我是前Pascal人,目前正在学习C#.我的问题如下:

下面的代码比开关更快吗?

int a = 5;

if (a == 1)
{
    ....
}
else if(a == 2)
{
    ....
}
else if(a == 3)
{
    ....
}
else if(a == 4)
{
    ....
}
else
    ....
Run Code Online (Sandbox Code Playgroud)

和开关:

int a = 5;

switch(a)
{
    case 1:
        ...
        break;

    case 2:
        ...
        break;

    case 3:
        ...
        break;

    case 4:
        ...
        break;

    default:
        ...
        break;


}
Run Code Online (Sandbox Code Playgroud)

哪一个更快?

我问,因为我的程序有类似的结构(许多很多"其他如果"语句).我应该把它们变成开关吗?

Guf*_*ffa 578

对于少数项目,差异很小.如果你有很多物品,你一定要使用开关.

如果一个开关包含五个以上的项目,则使用查找表或哈希列表实现.这意味着与if:s列表相比,所有项目都获得相同的访问时间,其中最后一个项目需要更长的时间才能到达,因为它必须首先评估每个先前的条件.

  • 是的,但是如果使用if-else-if链,您可以根据它们变为真实的可能性来排序条件. (94认同)
  • 是的,但是前4-5个案例必须接近100%的出现才能弥补较慢的情况. (69认同)
  • 如果决策指向切换/跳转表,大多数现代编译器是否应该优化深度if/else if/else if/else?这就是说; 这应该没关系,编译器会优化它,为什么不编写最易读的代码呢? (28认同)
  • 从我的观点来看,switch也比if-elseif链更具可读性.这也很容易出现错误,如混合if-else; 如果别的; 在其中有其他副作用.使用开关你会立即看到n-fork,而连续的if-else-if-else可能会有些隐藏. (13认同)
  • @Dean J:是的,通常你应该编写最易读的代码,即使性能有所不同.如果您需要优化代码,它可能仍然有所作为.为了使编译器以您描述的方式优化代码,它必须对该值有更多的了解,即知道多次读取该值是否有任何副作用,因为将代码更改为开关只会读取一次该值. (12认同)
  • 如果性能增量可以忽略不计,我将始终使用`switch()`语句.您是否曾尝试在Visual Studio中调试大量的`if()`语句树?你会烧掉你的F10按钮,试图弄清楚哪个`if()`语句是匹配的; `switch()`语句会立即带你到匹配的情况. (4认同)
  • 这里提到的查找表取决于输入数据; 对于基于字符串的开关:当然,它将是一个哈希列表; 但是对于大多数基于整数的开关(特别是对于连续的候选者),它将是一个直接的IL`开关 (3认同)
  • @MarcGravell:是的,IL`witch`指令是一个查找表. (2认同)

Wed*_*dge 168

你为什么在乎?

99.99%的时间,你应该不在乎.

这些微优化不太可能影响代码的性能.

此外,如果您需要关心,那么您应该对代码进行性能分析.在这种情况下,找出switch case和if-else块之间的性能差异将是微不足道的.

编辑:为了清楚起见:实现更清晰,更易于维护的设计.通常,当遇到巨大的switch-case或if-else块时,解决方案是使用多态.找到正在改变并封装它的行为.我之前必须处理这样庞大,丑陋的开关案例代码,而且通常并不难以简化.但是哦太满意了.

  • 我绝对不同意.你绝对应该关心,而不是因为性能,但这也会影响代码的可读性和可维护性.并且,正如其他人所提到的,您可能会考虑更好地利用多态性. (103认同)
  • 思维的类型"你永远不需要关心因为绩效从来都不是问题".任何程序员怎么能考虑这个呢?作为程序员,你需要知道在幕后发生了什么,知道编译器并使用它的大部分时间,因为有一天这些额外的MS可能会节省你的一天.来自C++,我在C#中看到了很多这种想法和行为,这很遗憾.而是回答他的问题然后忽视它. (7认同)
  • 哦,我同意你应该始终关心可读性和可维护性.重写一个巨大的开关/案例块的正确方法可能是多态(顺便提一下,它可能稍慢,但你不应该关心).宏优化(良好设计)总是优于微优化(更快的语句). (5认同)
  • @GrahamS,这有点像是一个误解.虚拟机可以像"真实"一样快速地运行...因为运行时可以比编译器更好地优化,因为它可以测量实际需要优化的内容.PS:我对博尔顿迷宫的java解决方案需要0.03375655565秒.已发布的获胜C#解决方案需要0.166秒,而C++位于第二位,时间为429.46秒,以找到错误的答案.而且CLR天生就慢了?嗯......我不这么认为蒂姆;-) (4认同)
  • 同意 - 如果您必须关心这种级别的优化,那么您可能一开始就不应该使用基于 CLR 的托管语言。 (2认同)
  • 考虑一个更一般的情况,你正在编写一个名为> 100k次的函数.我倾向于将这些称为"乘数".例如,递归函数中的for循环中的if语句具有来自循环和函数的2个乘数.对if语句的一个小改进可以带来巨大的性能提升.在设计时这样思考可以帮助防止导致您必须使用分析工具的问题.这是一个合法的问题,不应该被忽视. (2认同)
  • @ wizard07KSU 100k?如果c#中的100k if/else比较可能会使你获得一毫秒的执行时间,其中只有一小部分由if/else比较组成.正如我所说,如果你有性能关键代码然后试图猜测哪种优化方法最好是不正确的,你需要分析你的代码.除非你需要,否则不要试图从代码块中减去纳秒. (2认同)
  • 可怕的答案。 (2认同)

Mic*_*ent 27

相信这种性能评估,开关盒更快.

这是结论:

结果表明,switch语句的执行速度比if-else-if梯形图快.这是由于编译器能够优化switch语句.对于if-else-if梯形图,代码必须按程序员确定的顺序处理每个if语句.但是,因为switch语句中的每个case都不依赖于早期的情况,所以编译器能够以提供最快执行的方式重新排序测试.


Vil*_*lx- 14

另一件需要考虑的事情是:这真的是你的应用程序的瓶颈吗?在极其罕见的情况下,确实需要优化此类型.大多数情况下,您可以通过重新思考算法和数据结构来获得更好的加速.


Sha*_*non 8

我说开关是要走的路,它既快又好练.

有各种链接,如(http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx),显示比较两者的基准测试.


Óla*_*age 7

不应该很难测试,创建一个在5个数字之间切换或ifelse的函数,将rand(1,5)抛入该函数并在计时时循环几次.


Ste*_*ven 6

Switch通常比ifs列表更快,因为编译器可以生成跳转表.列表越长,switch语句在一系列if语句中越好.

  • Noet,跳转表仅适用于(IIRC)连续值.编译器为复杂的非连续选项发出跳​​转表和breq的混合并不罕见. (3认同)

jfc*_*tte 5

从技术上讲,它们产生完全相同的结果,因此它们应该以几乎相同的方式进行优化.但是,编译器有更多机会使用跳转表优化切换表而不是ifs.

我在这里谈论一般情况.对于5个条目,假设您按频率对条件进行排序,则对ifs执行的平均测试次数应小于2.5.除非在一个非常紧凑的循环中,否则几乎不会成为写回家的瓶颈.


Joe*_*oey 5

switch如果可能的话,通常会被编译器翻译成一个查找表。因此,查找任意案例是 O(1),而不是在找到您想要的案例之前实际进行一些案例比较。

所以在很多情况下if/else if链会更慢。不过,根据您的案件被击中的频率,可能没有任何区别。


ann*_*ata 5

更重要的是交换机的性能优势(相对较小,但值得注意)是可读性问题.

我发现一个switch语句在intent和纯空格中非常清晰,与ifs链相比.


小智 5

我不确定,但我相信一个或另一个的速度会根据您使用的编程语言而改变.

我通常更喜欢使用开关.这样代码就很容易阅读.

  • 有趣的是,我认为如果 else 更干净:DI 认为选择最具可读性的内容。 (2认同)