Swift 什么';如果为零,两者之间的区别是什么可选…;如果让u=可选…;
我需要测试返回可选值的表达式是否为Swift 什么';如果为零,两者之间的区别是什么可选…;如果让u=可选…;,swift,optional,Swift,Optional,我需要测试返回可选值的表达式是否为nil。这看起来很简单,但代码如下 if nil != self?.checklists.itemPassingTest({ $0 === note.object }) { … } 不知什么原因,我觉得它很不舒服 if let item = self?.checklists.itemPassingTest({ $0 === note.object }) { … } 看起来好多了,但我其实不需要这个东西,我只需要知道有没有退货。因此,我使用了以
nil
。这看起来很简单,但代码如下
if nil != self?.checklists.itemPassingTest({ $0 === note.object }) {
…
}
不知什么原因,我觉得它很不舒服
if let item = self?.checklists.itemPassingTest({ $0 === note.object }) {
…
}
看起来好多了,但我其实不需要这个东西,我只需要知道有没有退货。因此,我使用了以下方法
if let _ = self?.checklists.itemPassingTest({ $0 === note.object }) {
…
}
我是不是错过了一些微妙的东西?我认为如果为零!=可选…
和如果let=可选…
在这里是等效的
更新以解决答案中的一些问题
nil!=var
和var!=nil
,尽管我通常使用var!=无
。在这种情况下,按!=nil
在块获得与if的布尔比较混合的块的布尔比较后(x,)=(10,20)
,用于循环,用于1…5
,case语句case(0):
,等等(注意:这些示例取自Swift编程语言)经过这么长时间,Swift 2.0让它变得毫无意义
if self?.checklists.contains({ $0 === note.object }) ?? false {
…
}
我个人认为这看起来令人不快,因为您将零与结果进行比较,而不是将结果与零进行比较:
if self?.checklists.itemPassingTest({ $0 === note.object }) != nil {
…
}
由于您只想确保它不是nil,并且不使用
项
,因此使用let
是没有意义的,如果let语法被称为可选绑定。它接受一个可选项作为输入,如果可选项不是nil,则返回一个必需的常量。这适用于公共代码模式,首先检查一个值是否为nil,如果它不是nil(如果它有一个值),则对其执行一些操作
如果可选的为nil,则停止处理,并跳过大括号内的代码
如果可选!=nil
语法更简单。它只是检查可选值是否为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!")
}
vs
生成相同的程序集代码:
; call to arc4random
callq _arc4random
; check if LSB == 1
testb $1, %al
; if it is, skip the println
je LBB0_1
movq $0, __Tv6if_let1iGSqSi_(%rip)
movb $1, __Tv6if_let1iGSqSi_+8(%rip)
jmp LBB0_3
LBB0_1:
movq $2, __Tv6if_let1iGSqSi_(%rip)
movb $0, __Tv6if_let1iGSqSi_+8(%rip)
leaq L___unnamed_1(%rip), %rax ; address of "set!" literal
movq %rax, -40(%rbp)
movq $4, -32(%rbp)
movq $0, -24(%rbp)
movq __TMdSS@GOTPCREL(%rip), %rsi
addq $8, %rsi
leaq -40(%rbp), %rdi
; call println
callq __TFSs7printlnU__FQ_T_
LBB0_3:
xorl %eax, %eax
addq $32, %rsp
popq %rbx
popq %r14
popq %rbp
retq
空速的答案告诉我们,让
和!=nil
生成相同的汇编代码,因此我强烈建议使用第一种方法
事实上,如果你有以下情况:
if let _ = optional {
do_something()
}
…并且您希望添加一些代码,现在您需要该可选代码,此更改将更容易、更快:
if let wrapped = optional {
do_something()
do_something_else(with: wrapped)
}
使用let
并编写可维护的代码。func-check(x:Int){/*arc4random()->x*/}
将输出从1000页减少到1.5页。:-)在这个例子中,我并不关心性能,但知道它们具有等效的二进制表示让我放心。考虑到苹果的swift示例中使用了of,我不认为一个未绑定的变量应该那么令人惊讶。正如这张海报所说,正如我在上面的另一篇评论中所说,源代码是人类可读的代码,因此应该表达人类如何表达逻辑。大声读出逻辑,它会说‘如果这不是零,那么……’,这准确地翻译为‘如果x!’无{…’在源代码中,这意味着更具可读性。老实说,我看不出“if let ux”对它有什么好处。也许这只是当你不关心一个或多个值时,能够进行模式匹配的副产品,为了支持这一点,它最终创建了“if let x”的废话。对于范围内的
是一个very不同的情况。在这种情况下,您运行循环的次数是特定的,但不需要索引值。我正要投票支持这个,但后来我想到了什么是源代码…人类可读的代码。虽然您是对的,如果您需要该值,将来更容易更改,但从其他语法更改也不难.更重要的是,在那之前(如果有的话),它不那么可读。想想看……大声读逻辑,它说‘如果这不是零,那么……’,这在源代码中准确地翻译为‘如果x!=nil{…’,这意味着它更可读。这就是为什么我改变了主意。
if let wrapped = optional {
do_something()
do_something_else(with: wrapped)
}