swift - 为什么这个开关在不详尽的情况下会编译?

标签 swift switch-statement

我有这个Result枚举:

public enum Result<T> {
    case success(T)
    case failure(Error)
}

并想实现CustomStringConvertible , 所以我做了。 (不要戳破这个问题,这个问题已经简化了:):

extension Result: CustomStringConvertible {

    public var description: String {
        switch self {
        case .success(let value as CustomStringConvertible):
            return "Result.success(\(value.description))"
        case .success(let value):
            return "Result.success(\(value))"
        case .failure(let error as CustomStringConvertible):
            return "Result.failure(\(error.description))"
        }
    }
}

在 Playground 中运行它完全符合要求。但是,它在最后的 r.description 上出错了. (同样的运行时故障发生在我的应用程序中,所以这与在 Playground 上无关。)

var r: Result<String> = .success("hello")
r.description

r = .failure(NSError(domain: "", code: 0, userInfo: nil))
r.description

struct MyError: Error { }
r = .failure(MyError())
r.description

经过大量的摸索和代码设置后,我发现这是因为 MyError未实现 CustomStringConvertible,因此开关匹配中没有任何情况。我认为这意味着垃圾从该方法返回。

那么,有人知道为什么这个开关可以编译吗?


编辑

在 Playground 上通过添加这样的最终案例修复此问题后:

case .failure(let error):
    return "Result.failure(\(error))"

它有效。但是,当我将它添加回我的应用程序时,编译器大胆地发出警告:warning: case is already handled by previous patterns; consider removing it - 这是 Swift 中的错误(不太可能)还是我误解了 Error 之间的关系和 CustomStringconvertible (更有可能)?

最佳答案

我假设您在定义 Result 类型的文件中导入 Foundation。好吧,这会产生(有时)编译器将 Swift 值桥接到 Objective-C 兼容对象的不良影响,这就是您的情况。

删除 import Foundation 子句将导致您的 switch 由于不详尽而不再编译。我怀疑 Foundation 导入将 .failure 案例中的 CustomStringConvertible 协议(protocol)桥接到某个 Objective-C 值,但不正确的值会崩溃应用程序。

关于swift - 为什么这个开关在不详尽的情况下会编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48795712/

相关文章:

php - 开关盒中的 0?

c++ - (C++/QT) 通过将字符串转换为 int 来使用带有字符串的 switch 语句

assembly - Switch Case 汇编语言

Linux如何使用rm和exclude开关

java - 用 java.lang.Boolean 和 switch 做三元逻辑

ios - NSLayoutManager:如何在只有可渲染字形的地方填充背景颜色

swift - 在 Swift 中使用 String 的 enumerateLines 函数

ios - 保持 TableView 之间的数组顺序?

ios - 使用 MapKit Swift 在两个坐标之间绘制路径

ios - 帖子的神秘网络问题。 Wifi 工作,手机不