在Swift中比较两个选项的最优雅方式

在Swift中比较两个选项的最优雅方式,swift,optional,Swift,Optional,我有两个AnyObject?变量,我想比较它们以获得引用等式: var oldValue: AnyObject? var newValue: AnyObject? ... if oldValue != newValue { changed = true } 但这不起作用,因为我显然无法直接比较两个选项。我希望行为就像我在Objective-C中比较ids一样,即: true如果两者都是nil true如果两者都有值且值也相等 false否则 有没有一种优雅的方法可以用Swift编写

我有两个
AnyObject?
变量,我想比较它们以获得引用等式:

var oldValue: AnyObject?
var newValue: AnyObject?
...
if oldValue != newValue {
    changed = true
}
但这不起作用,因为我显然无法直接比较两个选项。我希望行为就像我在Objective-C中比较
id
s一样,即:

  • true
    如果两者都是
    nil
  • true
    如果两者都有值且值也相等
  • false
    否则
有没有一种优雅的方法可以用Swift编写(理想情况下无需编写自定义扩展)

这是我想到的最好的:

if !(oldValue != nil && newValue != nil && oldValue == newValue)

不太漂亮(

假设您使用的是可比较的实体,这将适用于任何情况:

func optionalsAreEqual<T: Comparable>(firstVal: T?, secondVal: T?) -> Bool{

    if let firstVal = firstVal, secondVal = secondVal {
        return firstVal == secondVal
    }
    else{
        return firstVal == nil && secondVal == nil
   }
}
func optionalsAreEqual(第一个值:T?,第二个值:T?)->Bool{
如果让firstVal=firstVal,则secondVal=secondVal{
return firstVal==secondVal
}
否则{
返回firstVal==nil&&secondVal==nil
}
}

它不是很短很甜,但它很有表现力、清晰,并且可以重复使用。

您可以使用
!=

来自Swift编程语言

Swift还提供了两个标识运算符(
==
!==
),用于测试两个对象引用是否都引用同一对象实例

一些好的例子和解释也在这里

在@PEEJWEEJ point上,执行以下操作将导致
false

var newValue: AnyObject? = "String"
var oldValue: AnyObject? = "String"

if newValue === oldValue {
   print("true")
} else {
   print("false")
}

我定义了一个自定义中缀运算符,其中包含引用类型和值类型的函数

func ==? <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, rhs = rhs {
        return lhs == rhs
    } else{ return lhs == nil && rhs == nil }
}
func ==? <T: AnyObject>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, rhs = rhs {
        return lhs === rhs
    } else{ return lhs == nil && rhs == nil }
}
infix operator ==? { associativity left precedence 130 }

var aString: String? = nil
var bString: String? = nil
print(aString ==? bString) // true

aString = "test"
bString = "test"
print(aString ==? bString) // true

aString = "test2"
bString = "test"
print(aString ==? bString) // false

aString = "test"
bString = nil
print(aString ==? bString) // false

class TT {}
let x = TT()

var aClass: TT? = TT()
var bClass: TT? = TT()
print(aClass ==? bClass) // false

aClass = TT()
bClass = nil
print(aClass ==? bClass) // false

aClass = nil
bClass = nil
print(aClass ==? bClass) // true

aClass = x
bClass = x
print(aClass ==? bClass) // true
func==?(左:T?、右:T?->Bool{
如果设lhs=lhs,则rhs=rhs{
返回lhs==rhs
}else{return lhs==nil&&rhs==nil}
}
func==?(左:T?、右:T?->Bool{
如果设lhs=lhs,则rhs=rhs{
返回lhs===rhs
}else{return lhs==nil&&rhs==nil}
}
中缀运算符==?{结合性左优先130}
变量aString:字符串?=nil
变量bString:字符串?=nil
打印(aString==?bString)//true
aString=“测试”
bString=“测试”
打印(aString==?bString)//true
aString=“test2”
bString=“测试”
打印(aString==?bString)//错误
aString=“测试”
bString=nil
打印(aString==?bString)//错误
类TT{}
设x=TT()
var aClass:TT?=TT()
变量b类:TT?=TT()
打印(aClass==?bClass)//false
aClass=TT()
b类=零
打印(aClass==?bClass)//false
aClass=nil
b类=零
打印(aClass==?bClass)//true
aClass=x
B类=x
打印(aClass==?bClass)//true
我喜欢这个解决方案。但我认为它不是用Swift 4编写的,因为我不能用Swift 4编译器编译它

所以我把他的代码转换成了Swift 4版本

请记住,如果您使用的Swift语言版本高于Swift 4.1,则此答案没有必要,因为默认情况下它提供了此功能。有关更多详细信息,请参阅

Swift 4版本的@Keith代码:

infix operator ==? : ComparisonPrecedence

func ==? <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, let rhs = rhs {
        return lhs == rhs
    } else {
        return lhs == nil && rhs == nil
    }
}

func ==? <T: AnyObject>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, let rhs = rhs {
        return lhs === rhs
    } else {
        return lhs == nil && rhs == nil
    }
}
中缀运算符==?:比较优先级
func==?(左:T?、右:T?->Bool{
如果设lhs=lhs,则设rhs=rhs{
返回lhs==rhs
}否则{
返回lhs==nil&&rhs==nil
}
}
func==?(左:T?、右:T?->Bool{
如果设lhs=lhs,则设rhs=rhs{
返回lhs===rhs
}否则{
返回lhs==nil&&rhs==nil
}
}

您可以为某些
可比较的
类型重载
=
运算符

public func ==<T: SomeType>(lhs: T?, rhs: T?) -> Bool {
    switch (lhs,rhs) {
    case (.some(let lhs), .some(let rhs)):
        return lhs == rhs
    case (.none, .none):
        return true
    default:
        return false
    }
}
public func==(左:T?,右:T?)->Bool{
开关(左、右){
大小写(.some(让左侧),some(让右侧)):
返回lhs==rhs
案例(.none,.none):
返回真值
违约:
返回错误
}
}

或者使用
===
比较
任何对象
,不过,就个人而言,我一开始不想使用
任何对象

你可以使用
!==
查看作为参考。真的是这样吗?!我一直忘了那个操作符!@sbarow我想你真的找到了。如果你想要代表,请发布答案。参考c比较是我想要的。我没有在变量得到值的地方发布代码。我不能忘记这个操作符,因为Javascript和它在
==
===
;-)中的古怪行为,虽然它不完全是我想要的,谢谢你发布这个,以防其他人正在寻找非引用比较。仅供参考,我认为,如果oldValue和newValue是对象,===将始终为false,除非它们实际设置为同一个对象。难道还不够相等吗?我假设这是用Swift 3编写的。我是对的,基思?