Swift: Switch 语句掉落行为

Swift: Switch statement fallthrough behavior

目前我有这个:

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 语句按照我想要的方式工作?

如果您希望通过其他 匹配的 案例而不是下一个(如 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")
}

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

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

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 语句)时,您会得到 "fall through"(这就是 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 语句。