swift 中的 Nil Coalescing (??) 运算符如何工作?

Sed*_*dem 2 null null-coalescing-operator swift

我的游乐场代码

let nickName: String? = nil
let fullName: String = "John Appleseed"

let informalGreeting = "Hi \(nickName ?? fullName)"
Run Code Online (Sandbox Code Playgroud)

嗨,约翰

let informalGreeting2 = "Hi \(fullName ?? nickName)"
Run Code Online (Sandbox Code Playgroud)

嗨可选(“约翰·苹果籽”)


我以为我理解第一种情况

let informalGreeting = "Hi \(nickName ?? fullName)"
Run Code Online (Sandbox Code Playgroud)

nickName 是 nil,所以输出必须是 "Hi \(fullName)" => "Hi John Appleseed"

在第二种情况下

let informalGreeting2 = "Hi \(fullName ?? nickName)"

第一个值 fullName 不是 nil ,所以我认为输出应该是 "Hi \(fullName)" => "Hi John Appleseed"。

但是为什么输出是一个可选的包装输出,就像这里

嗨可选(“约翰·苹果籽”)

Mar*_*n R 5

有两个??运算符:

public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T

public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
Run Code Online (Sandbox Code Playgroud)

如果我们通过忽略第二个参数是一个可能抛出的自动闭包来简化声明,我们得到

public func ??<T>(optional: T?, defaultValue: T) -> T    // (1)

public func ??<T>(optional: T?, defaultValue: T?) -> T?  // (2)
Run Code Online (Sandbox Code Playgroud)

在 中nickName ?? fullName,第一个参数是可选的,第二个参数是非可选的,这意味着使用第一个变体,结果是非可选的:

nickName ?? fullName   // (String? ?? String) -> String
Run Code Online (Sandbox Code Playgroud)

如果nickName != nil那么结果是解包的 (!) nickName,否则fullName.

在 中fullName ?? nickName,第一个参数是非可选的,第二个参数是可选的。这与任何那些函数声明都不匹配。

编译器所做的是将第一个参数“包装”到一个可选参数中以使其编译(使用第二个变体)。结果是一个可选的:

fullName ?? nickName   // (String? ?? String?) -> String?
Run Code Online (Sandbox Code Playgroud)

结果永远是Optional(fullName)

在已编译的项目中,您还将收到警告

警告:nil 合并运算符“??”的左侧 具有非可选类型“字符串”,因此从不使用右侧

第二种变体通常在链接 nil-coalescing 运算符时使用:

let result = optA ?? optB ?? optC ?? nonOptD
                  (2)     (2)     (1)
Run Code Online (Sandbox Code Playgroud)