我有这个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/