在以下代码中,值的推断类型和动态类型之间似乎存在不一致性(超出了静态方面的预期通用性):
// playground values in Xcode 7.0.1 (7A1001)
// (same behaviour in a release build)
let oi: Int? = nil // nil
let ooi: Int?? = nil // nil
let os = [oi, ooi] // [{nil}, nil]
let anys: [Any] = [oi, ooi] // [nil, nil]
oi == nil // true
ooi == nil // true
os[0] == nil // false
os[1] == nil // true
os[0].dynamicType // Optional<Optional<Int>>.Type
os[1].dynamicType // Optional<Optional<Int>>.Type
anys[0].dynamicType // Optional<Int>.Type
anys[1].dynamicType // Optional<Optional<Int>>.Type
(os[0] as Any).dynamicType // Optional<Optional<Int>>.Type
(os[1] as Any).dynamicType // Optional<Optional<Int>>.Type
os[0]! // nil
os[1]! // fatal error: unexpectedly found nil while unwrapping an Optional value
例如,我们不应该期望os[0].dynamicType
返回Optional<Int>.Type
吗?
当你看到let os = [oi, ooi] // [{nil}, nil]
时,花括号很重要,因为它们表示数组的第一项确实有一个值,这个值是nil(我知道这听起来可能很奇怪)。
如果你做os.dynamicType
,你会得到Array<Optional<Optional<Int>>>.Type
。
使用下面的代码可以更清楚:
switch os[0]
{
case .None: print("None")
case .Some(let value): print("Some") // "Somen"
switch value
{
case .None: print("None") // "Nonen"
case .Some(let value): print("Some")
}
}
这也是为什么os[0]!
等于nil
而不会崩溃的原因。
在我看来,当您处理多个可选层时,将可选视为Struct
更容易。