Swift 可选 - 不同的展开方式

Swift Optionals - Different ways of unwrapping

我马上开始:

有什么区别:

var test: String?
test = "this is an optional string"

if test != nil {
    println("\(test!) IS NOT nil")
} else {
    println("test is nil")
}

if let test = test {
    println("\(test) IS NOT nil")
} else {
    println("test is nil")
}

两者在 playground 中输出相同的结果。

我知道隐式展开不被认为是安全的(在大多数情况下)但是,在这里我在展开之前检查值是否为 nil?

这两种方法都有效吗?是否存在不同的情况,其中一种被认为是更好的选择?

Are both methods valid, and are there different scenarios where one is considered the better choice?

if-let 形式在任何情况下都是更好的选择。! 的正确发音是 "I swear on my program's life,",因为你是。

你的例子是平凡的形式,在平凡的形式中很难看出问题是如何发生的。我 只是 针对 nil 测试了这个。会出什么问题?但是软件在发展,软件在变化。您的 != nil 检查与人们使用了几十年的 C 和 Java 检查相同,并导致程序崩溃了几十年。实际上很容易错过必要但不是编译器要求的测试。人们一直都在这样做。

当您重新安排代码并将 println 移动到一个函数中时,您是否记得也移动了 if 测试?在大型函数中,if 测试可能在顶部完成,您是否记得在使用 ! 之前完成所有这些测试?重构后仍然如此吗?错误修复后?对于每次代码更改?

如果您忘记用 if-let 测试 nil,那么编译器将阻止您。如果您忘记使用 != nil 进行测试,则会发生崩溃;希望,如果你很幸运,在单元测试中。如果不是那么幸运,在现场。

也就是说,if-let 并不是唯一好的机制。您还可以 map 可选值、使用零合并 (??)、可选链接 (?.),这些都是避免错误的绝佳工具。但是 Apple 故意选择 !(在 Unix 中严肃地称为 "bang")。它很危险,只有在其他选项不可行时才应格外小心。

最后,如果您编写的代码完美无缺,则不需要编译器强加的安全性。您可以使用汇编程序编写代码,完全使用全局内存,并避免我们使用的许多抽象成本。但是人类程序员往往会犯很多小错误,这就是为什么你应该避免 !.