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

Swift switch statement considered all cases of Int, but compiler still display error(Swift switch 语句考虑了所有 Int 情况,但编译器仍然显示错误)

本文介绍了Swift switch 语句考虑了所有 Int 情况,但编译器仍然显示错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 Swift 中的 switch 语句必须是详尽的,否则我们必须提供默认情况.我在网上看到下面的代码,switch语句已经覆盖了Int中的所有情况,但是编译器仍然显示switch must be穷举的错误信息,考虑添加一个default子句.我有什么遗漏吗?

I understand switch statement in Swift must be exhaustive, otherwise we have to provide an default case. I saw the code below online, the switch statement already have covered all cases in Int, but the compiler still display error message that switch must be exhaustive, consider adding a default clause. Is there something I'm missing?

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
        }
    }
}

推荐答案

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

Update for Swift 3: Swift 3 introduced ClosedRange which makes it possible to define a range like 1...Int.max including the largest possible integer (compare Ranges in Swift 3). So this compiles and works as expected, but still requires a default case to satisfy the compiler:

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")
        }
    }
}

还有其他 Swift 编译器没有的错误报告正确确定 switch 语句的详尽性,例如如 https://bugs.swift.org/browse/SR-766,其中 Apple工程师乔·格罗夫评论:

There are other bug reports where the Swift compiler does not correctly determine the exhaustiveness of switch-statements, such as https://bugs.swift.org/browse/SR-766, where Apple engineer Joe Groff commented:

不幸的是,像 '...' 和 '<' 这样的整数运算对 Swift 来说只是简单的函数,所以很难进行这种分析.即使对整数区间有特殊情况的理解,我认为在模式匹配的完全一般性中仍然存在穷举匹配无法确定的情况.我们可能最终能够处理一些案件,但这样做总会涉及特殊情况.

Unfortunately, integer operations like '...' and '<' are just plain functions to Swift, so it'd be difficult to do this kind of analysis. Even with special case understanding of integer intervals, I think there are still cases in the full generality of pattern matching for which exhaustiveness matching would be undecidable. We may eventually be able to handle some cases, but there will always be special cases involved in doing so.

<小时>

旧答案:编译器并不聪明,无法识别您已涵盖所有可能的情况.一种可能的解决方案是添加默认值fatalError() 的情况:


Old answer: The compiler is not so smart to recognize that you have covered all possible cases. One possible solution is to add a default case with a 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")
    }
}

或者将 case 0: 设为默认大小写:

Or make case 0: the default case:

var kind: Kind {
    switch self {
    case let x where x > 0:
        return .Positive
    case let x where x < 0:
        return .Negative
    default:
        return .Zero
    }
}

(备注:我最初认为以下会正常工作不需要默认情况:

(Remark: I initially thought that the following would work correctly without needed a default case:

var kind: Kind {
    switch self {
    case 0:
        return .Zero
    case 1 ... Int.max:
        return .Positive
    case Int.min ... -1:
        return .Negative
    }
}

然而,这个编译,但在运行时中止,因为你不能创建范围 1 ... Int.max.有关此的更多信息问题可以在文章Ranges and Intervals in Swift中找到.)

However, this compiles, but aborts at runtime because you cannot create the range 1 ... Int.max. More information around this problem can be found in the article Ranges and Intervals in Swift.)

这篇关于Swift switch 语句考虑了所有 Int 情况,但编译器仍然显示错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:Swift switch 语句考虑了所有 Int 情况,但编译器仍然显示错误