什么是 `switch` 语句?

what are `switch` statements for?

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();
}
如果需要,

Plus if 可让您进行不等式比较(><!=)。我可能会发现 switch 更有用的唯一情况是当你不在内部使用 break 语句时:但这种情况并不经常发生,而且我发现它在代码质量方面很糟糕。

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

一些语言也允许在 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 上更难分析的优化,例如使用二进制搜索来确定正确的大小写而不是线性搜索,甚至使用跳转 table 或算术。例如。下面的开关

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。是的,与更通用的构造相比,结构化编程构造在它们可以表达的内容上是严格劣等的。但它们更具可读性,使意图更清晰,并且往往更安全,更易于维护。

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

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

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

这是一种非常简洁的表达方式,尤其是当您可能还依赖于掉落行为时。

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