Swift 可选项和等于运算符

6
寻找文档、名称或链接,介绍这个特定行为,它类似于可选绑定但在文档的该部分中没有被提到。
我可以使用“==”运算符测试可选项,并针对nil和其实际值进行测试,而无需进行任何明确的解包操作。
var toggle: Bool? = nil
if (toggle == true || toggle == nil) {
    // do something
}

这段代码可以编译并按预期运行,但是需要注意的是,我没有显式地取消 toggle!== 已经安全地为我完成了这个操作。
这种方式很方便,但当我注意到它时,我有点惊讶。这只是默认的 == 实现行为吗?还是语言中发生了其他事情?感谢您的见解。

3
如果你在 == 上按住 Command 键点击,你会发现有一个 public func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool 函数,它接受两个可选类型作为操作数。 - Martin R
确实,但为什么它应该这样呢?这是语言设计上的哲学问题吗?还是只是一种方便之举?或者我想得太多了? - Ben Zotto
3
我认为这很方便。在Swift 3中,接受可选项的比较运算符被删除:https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md。但是相等运算符还存在:“==”和“!=”的变体仍然有用,并且它们的结果不会出人意料,所以它们将保留。 - Martin R
1
@BradThomas:您使用的是哪个Xcode版本?请参考https://dev59.com/V7Dla4cB1Zd3GeqP6E-X#56870050。 - Martin R
@MartinR 10.3 好的,谢谢,我会去查看的。 - Bradley Thomas
显示剩余2条评论
1个回答

11

Swift有一个等式运算符,接受两个可选值(Equatable基础类型的值):

public func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool

实现可以在Optional.swift中找到:
public func == <T: Equatable>(lhs: T?, rhs: T?) -> Bool {
  switch (lhs, rhs) {
  case let (l?, r?):
    return l == r
  case (nil, nil):
    return true
  default:
    return false
  }
}

这段代码的作用是:如果两个操作数都是nil,或者它们都不是nil并且解包后的值相等,则它们相等。
在Swift 3中,类似的比较运算符如<已经被移除,详见SE-0121 Remove Optional Comparison Operators。根据该提案,移除接受可选类型操作数的版本的<, <=, >, 和 >=比较运算符,而接受可选类型操作数的==!=将继续保留,因为它们仍然很有用且结果很明显。
所以,这段代码能够按预期工作。
let b: Bool? = nil
print(b == true) // prints "false"

但正如Matt指出的那样,使用隐式解包可选项无法完成此操作,这里左操作数将被解包:

let b: Bool! = nil
print(b == true) // crashes

2
警告:不要尝试使用隐式解包可选项。可能会发生可怕的事情(商标)。 - matt
1
@matt 在 Swift 5.6 中没有发生任何事情。应用程序不会崩溃。 - Mohammad Daihan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接