我尝试编写自定义模式匹配,让我可以启用错误并匹配错误代码。请参阅以下示例:
enum ErrorCode: Int {
case notSoDumb
case dumbError
}
let myError = NSError(domain: "My domain", code: ErrorCode.dumbError.rawValue, userInfo: nil)
func ~=(pattern: ErrorCode, value: NSError) -> Bool {
return (ErrorCode(rawValue: value.code) == pattern)
}
switch myError {
case ErrorCode.notSoDumb:
print("Not a dumb error")
case ErrorCode.dumbError:
print("Super dumb error")
default:
print("No matches!")
}
我的switch语句中的第一个案例的错误为Enum case 'notSoDumb' is not a member of type 'NSError'
。如果我用整数替换ErrorCode
枚举(并更新我的自定义~=
运算符以匹配Int
和NSError
,则一切正常。
答案 0 :(得分:7)
这是[{3}} enum
个案例匹配案例;编译器错误地认为它总是使用a known bug而不是enumeration case pattern。
在修复之前,强制编译器进入“表达式模式”的一种方法是首先将案例绑定为临时的:
let notSoDumbErrorCode = ErrorCode.notSoDumb
let dumbErrorCode = ErrorCode.dumbError
switch myError {
case notSoDumbErrorCode:
print("Not a dumb error")
case dumbErrorCode:
print("Super dumb error")
default:
print("No matches!")
}
然而,这非常笨重。一个更好的解决方法是使用struct
与静态成员而不是enum
:
import Foundation
struct ErrorCode : Equatable, RawRepresentable {
let rawValue: Int
static let notSoDumb = ErrorCode(rawValue: 0)
static let dumbError = ErrorCode(rawValue: 1)
}
let myError = NSError(domain: "My domain",
code: ErrorCode.dumbError.rawValue,
userInfo: nil)
func ~=(pattern: ErrorCode, value: NSError) -> Bool {
return value.code == pattern.rawValue
}
switch myError {
case ErrorCode.notSoDumb:
print("Not a dumb error")
case ErrorCode.dumbError:
print("Super dumb error")
default:
print("No matches!")
}
这也使您可以在以后通过扩展添加其他错误代码(它的行为更像是一个打开的枚举)。虽然它确实删除了init(rawValue:)
的验证,但这可能是可取的,也可能不合适(但您可以随时实现自己的init?(rawValue:)
)。
或者,expression pattern,您可以坚持使用enum
,但在模式匹配时使用中间函数调用来强制编译器进入“表达式模式”:
enum ErrorCode : Int {
case notSoDumb
case dumbError
}
// ...
func identity<T>(_ t: T) -> T { return t }
switch myError {
case identity(ErrorCode.notSoDumb):
print("Not a dumb error")
case identity(ErrorCode.dumbError):
print("Super dumb error")
default:
print("No matches!")
}
答案 1 :(得分:0)
有趣的是,尽管 @Hamish bug 中链接的 answer 仍然处于打开状态,但现在可以编译并运行:
import Foundation
enum ErrorCode: Int {
case notSoDumb
case dumbError
}
let myError = NSError(domain: "My domain", code: ErrorCode.dumbError.rawValue, userInfo: nil)
func ~=(pattern: ErrorCode, value: NSError) -> Bool {
return (ErrorCode(rawValue: value.code) == pattern)
}
switch myError {
case .notSoDumb:
print("Not a dumb error")
case .dumbError:
print("Super dumb error") // "Super dumb error\n"
default:
print("No matches!")
}
我最好的猜测是这与 SE-0287