不在'if case'语句中的条件

And*_*nko 31 swift

我有一个枚举:

enum E {
    case A, B, C(Int)
}

let a: E = .A
Run Code Online (Sandbox Code Playgroud)

这是我如何检查是否a等于.B

if case .B = a {
    // works fine
}
Run Code Online (Sandbox Code Playgroud)

但是我如何检查相反的情况呢?(a 相等.B)?这是我试过的:

if case .B != a { // Variable binding in a condition requires an initializer
    // ...
}

if !(case .B = a) { // Expected ',' separator
    // ...
}
Run Code Online (Sandbox Code Playgroud)

当然,我可以这样做:

if case .B = a {
    // ...
} else {
    // put your code here
}
Run Code Online (Sandbox Code Playgroud)

但这很尴尬,还有使用switch声明.还有更好的选择吗?


编辑:解决方案@Greg建议如果案例没有关联值,但是如果它们确实==需要重载运算符.很抱歉没有在第一时间澄清这一点.

vac*_*ama 26

这个"答案"只不过是以更紧凑的方式编写尴尬的解决方案.如果你只关心一个值不是某个枚举值的情况,你可以像这样把它写在一行中,else紧跟在then then子句后面:

enum E {
    case A, B(String), C(Int)
}

let a: E = .B("Hello")

if case .A = a {} else {
    print("not an A")
}

if case .B = a {} else {
    print("not a B")
}

if case .C = a {} else {
    print("not a C")
}
Run Code Online (Sandbox Code Playgroud)

  • 读取此代码的人可能不会注意到`{} else`部分,但是,是的,否则它是一个可行的解决方案:) (2认同)

Gre*_*reg 7

您正在使用single = sign,这是一个赋值运算符.你必须使用double ==这是一个比较而且不使用case .A,使用EA是正确的方法:

if E.A == a {
    // works fine
    print("1111")
}

if E.B != a {
    // works fine
    print("2222")
}

if E.B == a {
    // works fine
    print("3333")
}
Run Code Online (Sandbox Code Playgroud)

扩展:

要使它与关联值一起使用,您必须实现Equatable协议,例如:

extension E: Equatable {}
func ==(lhs: E, rhs: E) -> Bool {
    switch (lhs, rhs) {
        case (let .C(x1), let .C(x2)):
            return x1 == x2
        case (.A, .A):
        return true

     default:
         return false
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,你必须处理所有的可能性,但我认为你有一个想法.

扩展:

我没有收到您的评论,但这对我很有用:

enum E {
    case A, B, C(Int)
}

extension E: Equatable {}
func ==(lhs: E, rhs: E) -> Bool {
    switch (lhs, rhs) {
        case (let .C(x1), let .C(x2)):
            return x1 == x2
        case (.A, .A):
            return true
        case (.B, .B):
            return true

     default:
         return false
    }
}

let a: E = .A
let b: E = .B
let c: E = .C(11)

if E.A == a {
    // works fine
    print("aaa true")
}
if E.A != a {
    // works fine
    print("aaa false")
}

if E.B == b {
    // works fine
    print("bbb true")
}

if E.B == b {
    // works fine
    print("bbb false")
}

if E.C(11) == c {
    // works fine
    print("ccc true")
}

if E.C(11) != c {
    // works fine
    print("1 ccc false")
}

if E.C(22) != c {
    // works fine
    print("2 ccc false")
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,它可以工作,但如果案例具有关联值则不行.抱歉没有发现这个问题. (4认同)
  • 正如我之前提到的,模式匹配允许我测试变量是否包含带有**ANY**关联值的`.C`(不是某些特定的值,如`0`,`1`,`22`或其他).并且编译器完全可以使用`if case .C = c {}`.这是唯一一个`==`运算符重载的情况,你坚持认为,它没有解决.这就是为什么这种解决方案不普遍的原因 (4认同)
  • 如果我重载`==`,它将适用于`.A`和`.B`,但不适用于具有关联值的`.C`。这就是为什么需要模式匹配。 (2认同)
  • 没有异议,确实如此,但是 `if EC != c` 不起作用。有时我需要检查“c”的值是否为“.C”,而不关心关联的值。 (2认同)

epo*_*gee 6

没有任何答案可以提及guardSwift 2引入的声明,它是上述工具的一个简洁的补充,如果你问我,如果你可以满足return你的功能或关闭内部的要求,那就是最干净的解决方案.else-块:

guard case .B = a else {
    // a does not match .B
    return
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅Apple的"Swift编程语言(Swift 2.2):语句".

  • 如果这确实是一个无效的案件,那么后卫是可以接受的.但是,如果这只是执行某些功能的流程的一部分,那么我认为守卫会错位.你怎么看? (11认同)
  • 如果你试图“通过”guard 子句,Swift 编译器会对你大喊大叫:`'guard' 主体可能不会通过,考虑使用 'return' 或 'break' 退出作用域`。我认为“保护”听起来没有“无效”那么消极,如果你从中立的角度看待它们,可能会让你在更多情况下使用`guard`子句,而不仅仅是防止灾难:) (2认同)