IUO 作为 Swift 4.2 中的字典键
IUO's as dictionary keys in Swift 4.2
以下代码在 Swift 4.2 (Xcode 10) 中的行为不再与在 Swift 4.1 (Xcode 9.4.1) 中的行为相同:
let key: String! = "key"
let dict: [AnyHashable:Any]? = ["key":"value"]
let val = dict?[key]
在Swift 4.1中,val
接收字典值("value"),而在Swift 4.2中为nil。
如果我删除 隐式解包可选 (IUO),或者将字典声明为 [String:Any]
,那么问题就消失了,所以两者都
let key: String = "key"
let dict: [AnyHashable:Any]? = ["key":"value"]
let val = dict?[key]
,以及
let key: String! = "key"
let dict: [String:Any]? = ["key":"value"]
let val = dict?[key]
导致 val
最终保留字符串 "value"。
这是 Swift 4.2 中的预期行为,还是编译器错误?
询问,因为我有一个巨大的代码库,其中键和字典都来自 Objective-C 代码,这有点难以改变。所以我想知道这种行为变化是否是永久性的,我应该开始更新代码中使用这种模式的许多地方,或者只是等到 Xcode 10 的稳定版本发布。
有一项提议 SE-0054 已在 Swift 4.2 中完全实施。以前有一个类型ImplicitlyUnwrappedOptional
,和Swift4.2的功能不一样(现在所有的IUO都是Swift4.2里的Optional
类型,不是ImplicitlyUnwrappedOptional
).
来自提案(强调我的):
If the expression can be explicitly type checked with a strong
optional type, it will be. However, the type checker will fall back to
forcing the optional if necessary. The effect of this behavior is that
the result of any expression that refers to a value declared as T!
will either have type T or type T?. For example, in the following
code:
let x: Int! = 5
let y = x
let z = x + 0
… x is declared as an IUO, but
because the initializer for y type checks correctly as an optional, y
will be bound as type Int?. However, the initializer for z does not
type check with x declared as an optional (there's no overload of +
that takes an optional), so the compiler forces the optional and type
checks the initializer as Int.
在你的例子中,key
变量被推断为 String?
类型,所以你仍然需要转换它。此代码有效:
let val = dict?[key!]
val
的值为 Optional("value")
至于为什么 [String:Any]
有效,根据引用中强调的部分, String?
不能在 String
上使用,所以编译器会强制解包(必要让它编译)。
以下代码在 Swift 4.2 (Xcode 10) 中的行为不再与在 Swift 4.1 (Xcode 9.4.1) 中的行为相同:
let key: String! = "key"
let dict: [AnyHashable:Any]? = ["key":"value"]
let val = dict?[key]
在Swift 4.1中,val
接收字典值("value"),而在Swift 4.2中为nil。
如果我删除 隐式解包可选 (IUO),或者将字典声明为 [String:Any]
,那么问题就消失了,所以两者都
let key: String = "key"
let dict: [AnyHashable:Any]? = ["key":"value"]
let val = dict?[key]
,以及
let key: String! = "key"
let dict: [String:Any]? = ["key":"value"]
let val = dict?[key]
导致 val
最终保留字符串 "value"。
这是 Swift 4.2 中的预期行为,还是编译器错误?
询问,因为我有一个巨大的代码库,其中键和字典都来自 Objective-C 代码,这有点难以改变。所以我想知道这种行为变化是否是永久性的,我应该开始更新代码中使用这种模式的许多地方,或者只是等到 Xcode 10 的稳定版本发布。
有一项提议 SE-0054 已在 Swift 4.2 中完全实施。以前有一个类型ImplicitlyUnwrappedOptional
,和Swift4.2的功能不一样(现在所有的IUO都是Swift4.2里的Optional
类型,不是ImplicitlyUnwrappedOptional
).
来自提案(强调我的):
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?. For example, in the following code:
let x: Int! = 5 let y = x let z = x + 0
… x is declared as an IUO, but because the initializer for y type checks correctly as an optional, y will be bound as type Int?. However, the initializer for z does not type check with x declared as an optional (there's no overload of + that takes an optional), so the compiler forces the optional and type checks the initializer as Int.
在你的例子中,key
变量被推断为 String?
类型,所以你仍然需要转换它。此代码有效:
let val = dict?[key!]
val
的值为 Optional("value")
至于为什么 [String:Any]
有效,根据引用中强调的部分, String?
不能在 String
上使用,所以编译器会强制解包(必要让它编译)。