我有以下枚举:
enum JSONData {
case dict([String:Any])
case array([Any])
}
我想使用 guard case let 进行模式匹配赋值类型转换。我不仅要确保 someData
是 .array
,而且它的关联类型是 [Int]
而不仅仅是 [任何]
。这可能用一个表达式吗?类似于以下内容:
let someData: JSONData = someJSONData()
guard case let .array(anArray as [Int]) = someData
else { return }
但是上面没有编译;错误是 无法使用类型为“[Int]”的向下转型模式值
。我知道这可以通过以下方式实现,但如果可能的话,我宁愿用一个表达式来实现。
guard case let .array(_anArray) = someData, let anArray = _anArray as? [Int]
else { return }
2018 年 4 月 27 日编辑:此情况的更新:您现在可以使用以下语法,只要转换类型不是 Collection
:
enum JSONData {
case dict([String:Any])
case array(Any) // Any, not [Any]
}
func f() {
let intArray: JSONData = .array(1)
guard case .array(let a as Int) = intArray else {
return
}
print("a is \(a)")
}
f() // "a is 1"
如果您尝试使用诸如 [Int]
之类的集合类型,您会收到错误消息 error: collection downcast in cast pattern is not implemented;改用对“[Int]”的显式向下转换
。
最佳答案
由于 Swift 模式匹配实现的限制,您尝试执行的操作是不可能的。居然叫了here :
// FIXME: We don't currently allow subpatterns for "isa" patterns that
// require interesting conditional downcasts.
This answer试图解释原因,但不尽如人意。但是,它们确实指出了一条有趣的信息,如果您不使用泛型作为关联值,这些信息可以使事情正常进行。
以下代码实现了单行代码,但失去了一些其他功能:
enum JSONData {
case dict(Any)
case array(Any)
}
let someData: JSONData = JSONData.array([1])
func test() {
guard case .array(let anArray as [Int]) = someData else {
return
}
print(anArray)
}
或者,可以通过枚举定义中的实用函数将基础值转换为 Any
来实现相同的衬里。此路由保留了案例与其关联值类型之间的良好关系。
enum JSONData {
case dict([String : Any])
case array(Array<Any>)
func value() -> Any {
switch self {
case .dict(let x):
return x
case .array(let x):
return x
}
}
}
// This coercion only works if the case is .array with a type of Int
guard let array = someData.value() as? [Int] else {
return false
}
关于swift - 具有关联类型类型转换的保护案例的单个表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45124104/