Swift switch语句考虑了Int的所有情况,但编译器仍然显示错误

Tho*_*hor 5 enums switch-statement swift

我理解Swift中的switch语句必须是详尽的,否则我们必须提供一个默认的情况.我在网上看到了下面的代码,switch语句已经涵盖了Int中的所有情况,但是编译器仍然显示错误消息,交换机必须是详尽的,考虑添加一个default子句.有什么我想念的吗?

extension Int {
    enum Kind {
        case Negative, Zero, Positive
    }

    var kind: Kind {
        switch self {
        case 0:
            return .Zero
        case let x where x > 0:
            return .Positive
        case let x where x < 0:
            return .Negative
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 13

更新Swift 3:引入了Swift 3 ClosedRange,可以定义一个范围,例如1...Int.max包含最大可能的整数(比较Swift 3中的范围).所以这个编译并按预期工作,但仍然需要一个默认的情况来满足编译器:

extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case 1...Int.max:
            return .positive
        case Int.min...(-1):
            return .negative
        default:
            fatalError("Oops, this should not happen")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有其他错误报告,其中Swift编译器无法正确确定switch语句的详尽性,例如https://bugs.swift.org/browse/SR-766,Apple工程师Joe Groff评论说:

不幸的是,像'...'和'<'这样的整数运算对于Swift来说只是简单的函数,因此很难进行这种分析.即使对特殊情况理解整数区间,我认为仍然存在模式匹配的完全普遍性的情况,其中穷举匹配将是不可判定的.我们最终可能能够处理一些案件,但这样做总会遇到特殊情况.


旧答案:编译器并不是很聪明地认识到你已经涵盖了所有可能的情况.一种可能的解决方案是添加一个默认情况fatalError():

var kind: Kind {
    switch self {
    case 0:
        return .Zero
    case let x where x > 0:
        return .Positive
    case let x where x < 0:
        return .Negative
    default:
        fatalError("Oops, this should not happen")
    }
}
Run Code Online (Sandbox Code Playgroud)

或者做出case 0:默认情况:

var kind: Kind {
    switch self {
    case let x where x > 0:
        return .Positive
    case let x where x < 0:
        return .Negative
    default:
        return .Zero
    }
}
Run Code Online (Sandbox Code Playgroud)

(备注:我最初认为以下内容可以正常工作而无需默认情况:

var kind: Kind {
    switch self {
    case 0:
        return .Zero
    case 1 ... Int.max:
        return .Positive
    case Int.min ... -1:
        return .Negative
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这会编译,但会在运行时中止,因为您无法创建范围1 ... Int.max.有关此问题的更多信息,请参阅Swift中的Ranges and Intervals一文.)