Nil Coalescing (??)运算符在Swift中是如何工作的?

3

这是我的Playground代码

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

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

Hi John

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

你好 Optional("John Appleseed")


我认为我理解了第一个案例

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

nickName为空,所以输出应该是"Hi \(fullName)" => "Hi John Appleseed"

在第二种情况下

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

如果fullName有值,则输出应该是"Hi \(fullName)" => "Hi John Appleseed" in my opinion。

但是为什么输出是Optional("John Appleseed")这样的可选包装输出呢?

Hi Optional("John Appleseed")

2个回答

6

有两个 ?? 操作符:

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

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

如果我们简化声明,忽略第二个参数可能是一个可抛出的自动闭包,我们得到以下内容:
public func ??<T>(optional: T?, defaultValue: T) -> T    // (1)

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

nickName ?? fullName 中,第一个参数是可选的,而第二个参数是非可选的,这意味着使用第一个变量,并且结果是非可选类型:
nickName ?? fullName   // (String? ?? String) -> String

如果nickName != nil,则结果为非空的nickName,否则为fullName
fullName ?? nickName中,第一个参数是非可选项,第二个参数是可选项。这与任何函数声明都不匹配。
编译器所做的是将第一个参数“包装”成可选项以使其编译(使用第二个变量)。结果是一个可选项:
fullName ?? nickName   // (String? ?? String?) -> String?

结果将始终是Optional(fullName)
在编译项目中,您还将收到以下警告:
warning: left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used
第二种变体通常用于链接nil-coalescing操作符:
let result = optA ?? optB ?? optC ?? nonOptD
                  (2)     (2)     (1)

1
问题在于昵称是可选的,所以在第二种情况下,您告诉它如果fullname为nil则打印nickname,但是nickname也可能为nil,因此它将打印Hi Optional("John Appleseed")。
当使用“??”时,始终将其放在可选变量之前,但在不可选的字符串之后,它将正常工作。 希望这可以帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接