在游乐场中运行以下代码段会出错:
let a: [Int]? = [1,2]
let b: [Int]? = [1,2]
a == b // value of optional type '[Int]?' not unwrapped; did you mean to use '!' or '?'?
为“更简单”的可选类型做类似的事情时可以使用:
var x: Int? = 10
var y: Int?
x == y // false
第一种情况,可选数组背后的原因是什么,不被允许?为什么Swift不能首先查看是否有nil
(.None
),如果不是,请进行实际的数组比较。
答案 0 :(得分:31)
它适用于更简单类型的原因是因为有==
版本为包含Equatable
类型的选项定义:
func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool
虽然Int
是Equatable
,但Array
不是(因为它可能包含一些不相同的东西 - 在这种情况下它是怎么回事)。所有Equatable
内容都有一个==
运算符,但并非==
运算符的所有内容都是Equatable
。
您可以专门为包含equatable类型的可选数组编写==
的特例版本:
func ==<T: Equatable>(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
}
}
您还可以将其概括为涵盖包含equatable元素的任何集合:
func ==<C: CollectionType where C.Generator.Element: Equatable>
(lhs: C?, rhs: C?) -> Bool {
switch (lhs,rhs) {
case (.Some(let lhs), .Some(let rhs)):
return lhs == rhs
case (.None, .None):
return true
default:
return false
}
}
答案 1 :(得分:8)
添加swift 3版本的Airspeed答案:
func ==<T: Equatable>(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
}
}
func ==<C: Collection where C.Iterator.Element: Equatable>(lhs: C?, rhs: C?) -> Bool {
switch (lhs,rhs) {
case (.some(let lhs), .some(let rhs)):
return lhs == rhs
case (.none, .none):
return true
default:
return false
}
}
答案 2 :(得分:-1)
更新:缺少的功能已在Swift 4.1中实现。
您的代码
let a: [Int]? = [1,2]
let b: [Int]? = [1,2]
a == b
从Xcode 9.3(Swift 4.1)开始编译并按预期工作。
最简单的方法是不使用可选数组并使用空数组([]
)而不是nil
- 如果您不需要区分这两种情况。
let a = [1,2]
let b = [1,2]
let c = []
a == b
b != c
当我为结构编写Equatable扩展时,它适用于我的情况。我没有使用属性categories: [Category]?
,而是将其更改为categories: [Category]
并将缺少的类别解析为空数组([]
)。