我有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
上出错了。 (在我的应用程序中发生了相同的运行时故障,因此它与在操场上无关。)
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,所以交换机中的任何情况都不匹配。我认为这意味着从该方法返回垃圾。
那么,有没有人知道为什么这个开关会编译?
修改
通过添加这样的最终案例在操场上修好:
case .failure(let error):
return "Result.failure(\(error))"
它有效。但是,当我将它添加回我的应用程序时,编译器具有发出警告的大胆:warning: case is already handled by previous patterns; consider removing it
- 这是Swift中的错误(不太可能)或者我误解了Error
和{{之间的关系1}}(更有可能)?
答案 0 :(得分:0)
我假设您在定义Foundation
类型的文件中导入Result
。好吧,这有一些(有时)不需要的编译器将Swift值桥接到Objective-C兼容对象的效果,这就是你的情况。
删除import Foundation
子句将导致您的交换机由于不详尽而不再编译。我怀疑Foundation
导入将CustomStringConvertible
协议从.failure
案例桥接到某个Objective-C值,但是一个不正确的值会导致应用崩溃。