Swift:切换声明的通过行为

Swift: Switch statement fallthrough behavior

目前我有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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语句的目标是,如果是真的,就打印每个case,而不是只打印匹配的第一个case。我想我可以用Fallthrough语句来实现这一点。然而,这让我怀疑它是如何工作的。为什么Fallthrough会自动打印行中的下一个案例,即使案例不匹配?我怎样才能让这个switch语句按我想要的方式工作呢?


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

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

1
2
3
4
5
6
7
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程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch (x)
{
    case 0:
        if (y == 3)
        {
    case 1:
            puts("hello");
        }
        else
        {
            puts("world");
        }

    case 2:
        puts("!");
}

然而,这种使用非常罕见,而且往往难以遵循(快速!如果是x == 1可以执行其他分支吗?.我没有测试过,但是如果你能用Swift做类似的事情,我会非常惊讶的。

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

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


如果你想找到其他匹配的案例而不是下一个(如fallthrough所做),那么switch不是合适的工具。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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")
}