if nil != optional ... 和 if let _ = optional ... 之间有什么区别?
What's the difference between if nil != optional … and if let _ = optional …
我需要测试 returns 可选的表达式是否为 nil
。这看起来很简单,但这是代码。
if nil != self?.checklists.itemPassingTest({ [=10=] === note.object }) {
…
}
出于某种原因,这在我看来很不愉快。
if let item = self?.checklists.itemPassingTest({ [=11=] === note.object }) {
…
}
对我来说看起来好多了,但我实际上并不需要该物品,我只需要知道是否有退货。所以,我使用了以下内容。
if let _ = self?.checklists.itemPassingTest({ [=12=] === note.object }) {
…
}
我是不是漏掉了什么微妙的东西?我认为 if nil != optional …
和 if let _ = optional …
在这里是等价的。
更新以解决答案中的一些问题
我没看出nil != var
和var != nil
的区别,虽然我一般用var != nil
。在这种情况下,在块获得与 if.
的布尔比较混合的块的布尔比较之后推送 != nil
Wildcard Pattern 的使用应该不足为奇或不常见。它们用于元组 (x, _) = (10, 20)
、for-in 循环 for _ in 1...5
、case 语句 case (_, 0):
等(注意:这些示例取自 Swift 编程语言)。
这个问题是关于两种形式的功能等效性,而不是关于编码风格的选择。该对话可以在 programmers.stackexchange.com.
上进行
经过这么长时间,Swift 2.0 变得毫无意义
if self?.checklists.contains({ [=13=] === note.object }) ?? false {
…
}
我个人认为这看起来很不愉快,因为您将 nil 与您的结果进行比较,而不是将您的结果与 nil 进行比较:
if self?.checklists.itemPassingTest({ [=10=] === note.object }) != nil {
…
}
因为你只想确保它不是 nil 而不是使用 item
所以使用 let
.
没有意义
if let
语法称为可选绑定。它接受一个可选项作为输入,如果可选项不为零,它会返回一个必需的常量。这适用于您首先检查值是否为 nil 的通用代码模式,如果它不是 nil(如果它有值),则对其进行处理。
如果可选的是 nil,处理停止并跳过大括号内的代码。
if optional != nil
语法更简单。它只是检查可选值是否为 nil。它会跳过为您创建所需的常量。
如果您不打算使用结果值,可选的绑定语法会造成浪费和混淆。在这种情况下使用更简单的 if optional != nil
版本。正如 nhgrif 指出的那样,它生成的代码更少,而且您的意图更加清晰。
编辑:
听起来编译器足够聪明,如果您编写“if let”可选绑定代码但最终没有使用您绑定的变量,它不会生成额外的代码。主要区别在于可读性。使用可选绑定会产生您将使用绑定的可选对象的期望。
经过优化,这两种方式大概是一样的
例如,在这种情况下,使用 swiftc -O -emit-assembly if_let.swift
编译以下两个:
import Darwin
// using arc4random ensures -O doesn’t just
// ignore your if statement completely
let i: Int? = arc4random()%2 == 0 ? 2 : nil
if i != nil {
println("set!")
}
对
import Darwin
let i: Int? = arc4random()%2 == 0 ? 2 : nil
if let _ = i {
println("set!")
}
生成相同的汇编代码:
; call to arc4random
callq _arc4random
; check if LSB == 1
testb , %al
; if it is, skip the println
je LBB0_1
movq [=12=], __Tv6if_let1iGSqSi_(%rip)
movb , __Tv6if_let1iGSqSi_+8(%rip)
jmp LBB0_3
LBB0_1:
movq , __Tv6if_let1iGSqSi_(%rip)
movb [=12=], __Tv6if_let1iGSqSi_+8(%rip)
leaq L___unnamed_1(%rip), %rax ; address of "set!" literal
movq %rax, -40(%rbp)
movq , -32(%rbp)
movq [=12=], -24(%rbp)
movq __TMdSS@GOTPCREL(%rip), %rsi
addq , %rsi
leaq -40(%rbp), %rdi
; call println
callq __TFSs7printlnU__FQ_T_
LBB0_3:
xorl %eax, %eax
addq , %rsp
popq %rbx
popq %r14
popq %rbp
retq
AirspeedVelocity 的答案告诉我们 let _ =
和 != nil
生成相同的汇编代码,因此我强烈建议使用第一种方法。
事实上,如果你有类似的东西:
if let _ = optional {
do_something()
}
...你想添加一些代码,现在你需要那个可选的,这个改变会更容易和更快:
if let wrapped = optional {
do_something()
do_something_else(with: wrapped)
}
使用let _ =
并编写可维护的代码。
我需要测试 returns 可选的表达式是否为 nil
。这看起来很简单,但这是代码。
if nil != self?.checklists.itemPassingTest({ [=10=] === note.object }) {
…
}
出于某种原因,这在我看来很不愉快。
if let item = self?.checklists.itemPassingTest({ [=11=] === note.object }) {
…
}
对我来说看起来好多了,但我实际上并不需要该物品,我只需要知道是否有退货。所以,我使用了以下内容。
if let _ = self?.checklists.itemPassingTest({ [=12=] === note.object }) {
…
}
我是不是漏掉了什么微妙的东西?我认为 if nil != optional …
和 if let _ = optional …
在这里是等价的。
更新以解决答案中的一些问题
我没看出
nil != var
和var != nil
的区别,虽然我一般用var != nil
。在这种情况下,在块获得与 if. 的布尔比较混合的块的布尔比较之后推送 Wildcard Pattern 的使用应该不足为奇或不常见。它们用于元组
(x, _) = (10, 20)
、for-in 循环for _ in 1...5
、case 语句case (_, 0):
等(注意:这些示例取自 Swift 编程语言)。
!= nil
这个问题是关于两种形式的功能等效性,而不是关于编码风格的选择。该对话可以在 programmers.stackexchange.com.
上进行经过这么长时间,Swift 2.0 变得毫无意义
if self?.checklists.contains({ [=13=] === note.object }) ?? false {
…
}
我个人认为这看起来很不愉快,因为您将 nil 与您的结果进行比较,而不是将您的结果与 nil 进行比较:
if self?.checklists.itemPassingTest({ [=10=] === note.object }) != nil {
…
}
因为你只想确保它不是 nil 而不是使用 item
所以使用 let
.
if let
语法称为可选绑定。它接受一个可选项作为输入,如果可选项不为零,它会返回一个必需的常量。这适用于您首先检查值是否为 nil 的通用代码模式,如果它不是 nil(如果它有值),则对其进行处理。
如果可选的是 nil,处理停止并跳过大括号内的代码。
if optional != nil
语法更简单。它只是检查可选值是否为 nil。它会跳过为您创建所需的常量。
如果您不打算使用结果值,可选的绑定语法会造成浪费和混淆。在这种情况下使用更简单的 if optional != nil
版本。正如 nhgrif 指出的那样,它生成的代码更少,而且您的意图更加清晰。
编辑:
听起来编译器足够聪明,如果您编写“if let”可选绑定代码但最终没有使用您绑定的变量,它不会生成额外的代码。主要区别在于可读性。使用可选绑定会产生您将使用绑定的可选对象的期望。
经过优化,这两种方式大概是一样的
例如,在这种情况下,使用 swiftc -O -emit-assembly if_let.swift
编译以下两个:
import Darwin
// using arc4random ensures -O doesn’t just
// ignore your if statement completely
let i: Int? = arc4random()%2 == 0 ? 2 : nil
if i != nil {
println("set!")
}
对
import Darwin
let i: Int? = arc4random()%2 == 0 ? 2 : nil
if let _ = i {
println("set!")
}
生成相同的汇编代码:
; call to arc4random
callq _arc4random
; check if LSB == 1
testb , %al
; if it is, skip the println
je LBB0_1
movq [=12=], __Tv6if_let1iGSqSi_(%rip)
movb , __Tv6if_let1iGSqSi_+8(%rip)
jmp LBB0_3
LBB0_1:
movq , __Tv6if_let1iGSqSi_(%rip)
movb [=12=], __Tv6if_let1iGSqSi_+8(%rip)
leaq L___unnamed_1(%rip), %rax ; address of "set!" literal
movq %rax, -40(%rbp)
movq , -32(%rbp)
movq [=12=], -24(%rbp)
movq __TMdSS@GOTPCREL(%rip), %rsi
addq , %rsi
leaq -40(%rbp), %rdi
; call println
callq __TFSs7printlnU__FQ_T_
LBB0_3:
xorl %eax, %eax
addq , %rsp
popq %rbx
popq %r14
popq %rbp
retq
AirspeedVelocity 的答案告诉我们 let _ =
和 != nil
生成相同的汇编代码,因此我强烈建议使用第一种方法。
事实上,如果你有类似的东西:
if let _ = optional {
do_something()
}
...你想添加一些代码,现在你需要那个可选的,这个改变会更容易和更快:
if let wrapped = optional {
do_something()
do_something_else(with: wrapped)
}
使用let _ =
并编写可维护的代码。