【问题标题】:Swift: Switch statement fallthrough behaviorSwift:切换语句失败行为
【发布时间】:2015-09-02 02:20:21
【问题描述】:

目前我有这个:

let somePoint = (1, 0)

switch somePoint {
case (0,0):
    print("origin") // does not print
    fallthrough
case (_, 0):
    print("y-axis") // prints y-axis. this makes sense
    fallthrough
case(0, _):
    print("x-axis") // prints x-axis (because of fallthrough? this should not print)
    fallthrough
case(-2...2, -2...2):
    print("in 5x5 box about the origin") // this prints and makes sense
default:
    print("somewhere else") // does not print
}

我使用此 switch 语句的目标是打印每个案例(如果它是真的),而不是只打印第一个匹配的案例。我想我可以用 fallthrough 声明来做到这一点。然而,这让我质疑它是如何工作的。为什么即使大小写不匹配,fallthrough 也会自动打印行中的下一个案例?我怎样才能让这个 switch 语句按我想要的方式工作?

【问题讨论】:

    标签: swift switch-statement


    【解决方案1】:

    Fallthrough 落入下一个案例,而不是下一个匹配的案例。该概念继承自 C switch 语句,其中每个 case 可以被认为是 goto 目标标签,switch 语句将执行带到第一个匹配的标签。

    在 C 中,switch 语句仅指示块内的执行位置开始。为了更加方便,您可以使用break 语句跳过switch 正文的其余部分,但没有什么强迫您这样做;如果你不这样做,执行会正常继续,就像cases 不存在一样。例如:

    switch (countdown)
    {
        case 3: puts("3...");
        case 2: puts("2...");
        case 1: puts("1...");
        case 0: puts("0!");
    }
    

    在任何地方都没有break,如果countdown 是3,那么你得到了整个东西(即使countdown 显然是3,而不是2、1 或0)。

    当执行从一个案例转到另一个案例而不是退出 switch 范围(例如,使用 break 语句)时,您会得到“失败”(这就是 Swift 的 fallthrough 关键字所做的)。

    这在 C 中是相关的,因为您可以在 switch 语句中使用任意复杂的结构,如果您愿意,可以重叠案例。这是一个合法的 C 程序:

    switch (x)
    {
        case 0:
            if (y == 3)
            {
        case 1:
                puts("hello");
            }
            else
            {
                puts("world");
            }
    
        case 2:
            puts("!");
    }
    

    然而,这种用法非常少见,而且通常很难遵循(快点!如果x == 1 可以执行else 分支吗?)。我还没有测试过,但如果你能用 Swift 做类似的事情,我会感到非常惊讶。

    一般来说,在 C 中,失败被认为是糟糕的风格,因为通常很难判断失败是自愿还是由于缺少 break 语句。 Swift 使用 fallthrough 语句解决了这个问题,它明确表明您希望在 switch 语句内继续执行下一个案例,而不是退出 switch 范围。

    在你的情况下,你不能使用 fallthrough 来获得你想要的,因为 fallthrough 只有在你需要的执行顺序是线性的时候才有用。您需要跳过无效的代码块,因此您需要使用if-else 序列而不是switch 语句。

    【讨论】:

    • 在C#中使用goto case X解决,无需新关键字即可轻松阅读
    • @LưuVĩnhPhúc,这是可能的,因为 C#(和 C/C++/等)案例(相对于 Swift)的性质有限,并不是 OP 真正想要的。他们想要转到另一个案例并开始搜索另一个匹配项。 C# goto case 不会重新评估,因为选择标准不是动态的。换句话说,你已经知道你要去哪里了。
    【解决方案2】:

    如果您希望通过其他匹配案例而不是下一个案例(就像fallthrough 所做的那样),switch 不是适合这项工作的工具。

    相反,您应该使用一系列if 语句,例如:

    Bool gotOne = false;
    if (somePoint.0 == 0 && somepoint.1 == 0) {
        print("origin")
        gotOne = true;
    }
    if (somepoint.1 == 0) {
        print("y-axis")
        gotOne = true;
    }
    if (somepoint.0 == 0) {
        print("x-axis")
        gotOne = true;
    }
    :
    if (! gotOne) {
        print("somewhere else")
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 2011-06-22
      相关资源
      最近更新 更多