Nil Coalescing(??)运算符如何快速工作?

时间:2017-04-10 11:20:17

标签: swift null null-coalescing-operator

我的Playground code

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

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

嗨约翰

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

你好可选(" John Appleseed")

我以为我理解第一个案例

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

nickName为nil,因此输出必须为" Hi \(fullName)" => "嗨John Appleseed"

在第二种情况下

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

第一个值fullName不是nil,因此输出应为" Hi \(fullName)" => "嗨John Appleseed"在我看来。

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

一样
  

你好可选(" John Appleseed")

2 个答案:

答案 0 :(得分:4)

有两个??运算符:

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

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

如果我们通过忽略第二个参数来简化声明 一个可能抛出autoclosure,我们得到

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 :(得分:1)

问题是昵称是可选的,所以在第二种情况下,你告诉你如果fullname是nil print nickname,但昵称可以是nil,那么它将打印Hi Optional(“John Appleseed”),

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

相关问题