swift - 如何对带参数的枚举进行 if-else 比较

标签 swift enums

语言:Swift2.3

例如,我将向您展示不同种类的枚举

enum Normal {
    case one
    case two, three
}

enum NormalRaw: Int {
    case one
    case two, three
}

enum NormalArg {
    case one(Int)
    case two, three
}   

Switch 可用于所有三个枚举,如下所示:

var normal: Normal = .one
var normalRaw: NormalRaw = .one
var normalArg: NormalArg = .one(1)

switch normal {
    case .one: print("1")
    default: break
}

switch normalRaw {
    case .one: print(normalRaw.rawValue)
    default: break
}

switch normalArg {
    case .one(let value): print(value)
    default: break
}

在 if-else 语句中,虽然我只能对 NormalNormalRaw 进行比较,但对于 NormalArg 会显示一条错误消息,所以我无法运行代码

Binary Operator '==' cannot be applied to operands of type NormalArg and _

这是代码示例:

if normal == .two { // no issue
    .. do something
}

if normalRaw == .two { // no issue
    .. do something
}

if normalArg == .two { // error here (the above message)
    .. do something
}

if normalArg == .one(_) { // error here (the above message)
    .. do something
}

if normalArg == .three { // error here (the above message)
    .. do something
}

有什么想法吗?我实际上并没有对这段代码做任何事情,我只是想知道为什么我们不能进行比较。

最佳答案

诀窍是不要实际使用 == 进行检查,而是在 if 语句中将 case 关键字与单个 = 结合使用。这在开始时有点违反直觉,但就像 if let 一样,您很快就会习惯它:

enum Normal {
    case one
    case two, three
}

enum NormalRaw: Int {
    case one = 1
    case two, three
}

enum NormalArg {
    case one(Int)
    case two, three
}


let normalOne = Normal.one
let normalRawOne = NormalRaw.one
let normalArgOne = NormalArg.one(1)

if case .one = normalOne {
    print("A normal one") //prints "A normal one"
}

if case .one = normalRawOne {
    print("A normal \(normalRawOne.rawValue)") //prints "A normal 1"
}

if case .one(let value) = normalArgOne {
    print("A normal \(value)") //prints "A normal 1"
}

要点是,在 Swift 中,如果您的枚举使用原始类型或者您没有关联值(试试看,您不能同时拥有两者),您只能免费获得枚举方程式。然而,Swift 不知道如何将案例与关联值进行比较——我的意思是它怎么可能呢?让我们看一下这个例子:

Normal.one == .one //true
Normal.one == .two //false

NormalRaw.one == .one //true
NormalRaw.one == .two //false

NormalArg.one(1) == .one(1) //Well...?
NormalArg.one(2) == .one(1) //Well...?
NormalArg.one(1) == .two //Well...?

也许这更清楚了为什么这不能开箱即用:

class Special {
    var name: String?
    var special: Special?
}

enum SpecialEnum {
    case one(Special)
    case two
}

var special1 = Special()
special1.name = "Hello"

var special2 = Special()
special2.name = "World"
special2.special = special1

SpecialEnum.one(special1) == SpecialEnum.one(special2) //Well...?

因此,如果您想要具有关联值的枚举,则必须自己在枚举中实现 Equatable 协议(protocol):

enum NormalArg: Equatable {
    case one(Int)
    case two

    static func ==(lhs: NormalArg, rhs: NormalArg) -> Bool {
        switch (lhs, rhs) {
        case (let .one(a1), let .one(a2)):
            return a1 == a2
        case (.two,.two):
            return true
        default:
            return false
        }
    }
}

关于swift - 如何对带参数的枚举进行 if-else 比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44061147/

相关文章:

c# - 枚举初始化的正确输出

java - 使用 Enum 作为功能齐全的对象(像本例一样使用动态调度)是否意味着滥用它或不是一个好的设计?

python - python 中的枚举转换器

swift - 如何使用 UIcollectionView 制作 prepareForSegue

ios - 如何将 xml 字符串分成元组?

ios - 如何处理Apple App Store "Limited time only"内购?

c# - C# 中的枚举求值

java - 为什么 EnumSet 或 EnumMap 可能比它们的散列对应物更高效?

ios - 使用 SFAuthenticationSession 将用户登录到 Microsoft Graph

swift - UICollectionView 单元格宽度