2017-10-06 141 views
1

Switch语句:我知道他们在做什么 - 根据惯例,我常常使用它们很多次,当我想根据Enum的值做不同的事情时,但现在它只是打我:为什么我们要使用它?它最初的目的是什么?我的意思是,这样的:switch语句是什么?

switch(myVar) { 
    case Foo: 
     doSomething(); 
     break; 
    case Bar: 
     doSomethingElse(); 
     break; 
    default: 
     justAnotherThing(); 
     break; 
} 

具有完全相同的行为:

if(myVar == Foo) { 
    doSomething() 
}else if(myVar == Bar) { 
    doSomethingElse(); 
}else { 
    justAnotherThing(); 
} 

if的让你做不平等的比较(><!=),如果你需要它。我可能会发现一个开关更有用的唯一情况是当你不使用内部的break声明时:但这种情况不会太频繁,我发现代码质量很糟糕。

我真的找不到使用switch而非if的任何好处......那么为什么要定义它?

+2

现在做相同的'if-else if'链有十个选择,或二十,你会发现它不是很可读。另外,编译器可能能够将'switch'优化成简单的跳转表,而不必评估每个条件直到找到“匹配”。并且请记住,如果没有“break”,那么在类C语言中(您似乎将其用作基础)的情况*会通过*到达下一个“case”。这在if-else if链中很难做到。 –

+0

至于阅读能力,我认为他们几乎是平等的 - 只要你保持一致的身份,并且你使用'switch'的情况下使用if-else if',否则if (myVar =='总是占用相同的空间将使所有可能的值对齐并且易于阅读 – olivarra1

+0

而在我的问题中,我通过删除'break'来提及fall-through行为,但这对可读性来说很糟糕:所以你有可能会或可能不会跳到下一个案件的案件,以及改变案件的顺序都会影响行为,我只是用这个“把戏”来比较或者比较一个开关,并试图避免出现其他情况。 – olivarra1

回答

4

某些语言还允许在switch语句中进行不等式比较,例如, Visual Basic中:

Select Case x 
    Case < 5 
    // ... 
    Case 7 
    // ... 
    Case 10 To 15 
    // ... 
    Case Else 
    // ... 
End Select 

基本上,是的,switch往往可以写成if/else if梯,与switch对一些比较值一个值进行比较的区别,if/else if可以做任何事在每一个分支。但即使如此,在所有的语言中都不是这种情况,例如在PowerShell中switch可以做很多的事情,你通常必须使用if为:

switch -Regex ($x) { 
    '^\d+$' {'Number'} 
} 

switch ($x) { 
    { $_ is [int] -or $_ is [double] } {'Number'} 
    { $_ is [string] } {'Text'} 
} 

但是,总的来说,switch更容易阅读比较单一的常见情况价值与一套有限的选择。此外,它还使编译器能够执行某些优化,这些优化在if/else if上难以分析,例如使用二进制搜索来确定正确的大小写而不是线性搜索,或者甚至使用跳转表或算术。例如。下面的开关

switch (x) { 
    case 0: 
    // Do something with 0 
    break; 
    case 1: 
    // Do something with 1 
    break; 
    case 2: 
    // Do something with 2 
    break; 
    ... 
} 

可以编译成

Action[] actions = { 
() => { /* Do something with 0 */ }, 
() => { /* Do something with 1 */ }, 
() => { /* Do something with 2 */ }, 
    ... 
}; 
if (x >=0 && x <= n) { 
    actions[x](); 
} 

等效的简单和switch局限在这种情况下的优化编译器有帮助的,因为有少得多的分析,以确定哪些整体结构正试图做到。

还有其他功能(有时可能是可疑的值),如Duff's device,或能够转入其他情况(或goto任意其他情况下,例如C#允许)。

您可能还会问为什么我们有if语句和循环而不是仅使用goto。是的,与更一般的构造相比,结构化编程构造一个接一个地被严格地表现为劣势。但它们更具可读性,使意图更清晰,并且趋于更安全和更易于维护。

2

switch是一个相当低级的语句,从这个意义上说,case语句中的代码被编译成内存中的连续指令块,只是有条件地跳入内存中(取决于当前所讨论的语言,现代高级语言的行为可能会非常不同)。这也是为什么你有失败的原因,一旦确定了起始地址,只需执行下面的所有指令,除非中断。

所以最初这是一种非常自然的方式来跳过或进入一个指令块。许多语言都采用了switch声明,很多可能是因为熟悉,但很多也有可能是因为它确实相当可读某些情况下,例如:

switch (someComplicatedCalculation($foo, $bar)) { 
    case CONSTANT_A: 
     ... 
    case CONSTANT_B: 
     ... 
    ... 
} 

这是一个非常简洁的方式来表达这一点,特别是当你也许也取决于跌倒的行为。

当然,其他语言从未采用switch,例如, Python,并且需要使用if..elif..else来代替。最后,您可以使用任一种语言构造编写类似的代码,这取决于您。