为什么nil合并算子?返回零?

时间:2017-06-02 13:40:41

标签: swift optional

考虑以下涉及 nil coalescing operator ??的示例:

let mysteryInc = ["Fred": "Jones", "Scooby-Doo": nil]

let lastname = mysteryInc["Scooby-Doo"] ?? "no last name"

print(lastname == nil)  // true

如上一个print语句所示, nil合并运算符的结果为nil

如果 nil coalescing operator 应该打开 Optional ,为什么它会返回nil

1 个答案:

答案 0 :(得分:10)

要查看此处发生了什么,请将字典指定为常量:

let name = mysteryInc["Scooby-Doo"]
print(type(of: name))

输出:

Optional<Optional<String>>

因此,name双重可选String??

当应用 nil coalescing operator 时,它将展开外部 Optional 并留下Optional<String>(又名String?)。在问题的示例中,Swift将字符串文字"no last name"视为类型String?,以便可以应用??

如果您检查name的值,您会发现它是Optional(nil)。所有词典查找都会返回 Optionals ,因为可能不存在(在这种情况下,它们会返回nil)。在这种情况下,mysteryInc字典的类型为[String: String?]。与"Scooby-Doo"对应的值为nil,然后将其包含在可选中(因为字典查找)成为Optional(nil)

最后,值Optional(nil)??解包。自Optional(nil) != nil起,Swift解包Optional(nil)并返回nil,而不是返回预期的"no last name"

这就是你可以从 nil coalescing operator 获得nil的方法。它解开了 Optional ;恰好是 Optional 中的nil

正如@LeoDabus在评论中指出的那样,处理这种情况的正确方法是在应用 nil coalescing operator 有条件地将名称转换为String >:

let lastname = mysteryInc["Scooby-Doo"] as? String ?? "no last name"

实际上,最好避免将 Optionals 作为词典的值,因为@Sulthan提出了这个原因:

mysteryInc["Fred"] = nil做了什么?

nil分配给字典条目会从字典中删除该条目,因此mysteryInc["Fred"] = nil不会将Optional("Jones")替换为nil,而是删除{{1}完全进入。要将"Fred"留在字典中并使其姓氏为"Fred",您需要指定nilmysteryInc["Fred"] = Optional(nil)