快速中的 Nil 凝聚 (??) 运算符如何工作?



My Playground 代码:

let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi (nickName ?? fullName)"

嗨约翰

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

嗨可选("约翰苹果种子")


以为我明白了第一种情况

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

昵称为 nil,因此输出必须是"Hi \(fullName)" => "Hi John Appleseed">

在第二种情况下

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

第一个值 fullName 不是 nil ,所以输出应该是 "Hi \(fullName)" => "嗨约翰苹果种子" 在我看来。

但是为什么输出是可选的包装输出,如下所示

嗨可选("约翰苹果种子")

有两个??运算符:

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).

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

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

链接 nil 合并运算符时通常使用第二种变体:

let result = optA ?? optB ?? optC ?? nonOptD
(2)     (2)     (1)

问题是昵称是可选的,所以在第二种情况下,你告诉如果全名是 nil 打印昵称,但昵称可以是 nil,所以它会打印 嗨可选("约翰苹果种子"),

使用时?? 总是在它前面放一个可选变量,但在它后面放一个不是可选的字符串,它会正常工作。 希望这有帮助。

相关内容

  • 没有找到相关文章

最新更新