【问题标题】:How to check if enum does not match a pattern?如何检查枚举是否与模式不匹配?
【发布时间】:2018-01-09 04:35:38
【问题描述】:

请注意,我已阅读此post,但该帖子使用 switch 语句,并且它应该在模式匹配时执行某些操作(返回 true)。另一方面,如果模式匹配并使用 if-case 语句,我不想​​做任何事情。

我有这个枚举:

enum MyEnum {
    case a
    case b(Int)
    case c
    case d
}

这是它的一个实例:

let myEnum: MyEnum = .a

如果myEnum 不是.b,现在我想做点什么。由于.b 有一个关联值,我不能简单地使用 if 语句检查:

if myEnum != .b { // compiler error
    // do my thing here
}

所以我必须使用 if-case 语句来匹配它:

if case .b(_) = myEnum {

} else {
    // do my thing here
}

但我真的很讨厌使用空 if 子句。这对我来说看起来很笨拙。我试图天真地这样做:

if case .b(_) != myEnum { // compiler error!
    // do my thing here
}

除了使用空的 if 子句之外,还有更好的方法吗?

无论模式是否匹配,我仍然有应该运行的代码,因此 guard 语句将不起作用。

【问题讨论】:

    标签: swift enums pattern-matching


    【解决方案1】:

    这纯粹是您自己代码的最小语义更改,但请注意,您可以简单地“丢弃”与 case 模式匹配内联的空 if 子句:

    if case .b(_) = myEnum {} else {
        // do your thing here
    }
    

    或者,省略 case b 的关联值的冗余模式匹配:

    if case .b = myEnum {} else {
        // do your thing here
    }
    

    这看起来有点像guard 子句,但没有退出范围。

    【讨论】:

      【解决方案2】:

      你可以使用guard:

      guard case .b = myEnum else { 
          // do your stuff here
          return 
      }
      

      缺点是你必须退出作用域...

      【讨论】:

      • 抱歉,我意识到我没有提供足够的上下文。我的代码不能在那之后返回。无论模式是否匹配,都需要执行一些代码。尽管如此,你值得一票!
      • @Sweeper 是的,在我发布答案后想到了这一点,所以我添加了一个关于这个的注释:)
      • 为什么不使用返回枚举(开关)状态的函数或计算属性。
      • 请注意,模式匹配中无需包含(_)
      【解决方案3】:

      怎么样:

      switch myEnum {
      case .b(_):
          break
      default:
          // do your thing here
      }
      

      【讨论】:

      • 无需在模式匹配中包含(_)
      【解决方案4】:

      在枚举上创建一个 var,计算您的值是否不是 .b(_)

      enum MyEnum {
      
          case a
          case b(Int)
          case c
          case d
      
          var notB: Bool {
              switch self {
              case .b(_):
                  return false
              default:
                  return true
              }
          }
      }
      
      MyEnum.a.notB // true
      MyEnum.b(1).notB  // false
      MyEnum.c // true
      MyEnum.d // true
      

      不是最好的答案,因为还有很多代码要做检查,但至少在你实际使用时检查只有一行。

      【讨论】:

        【解决方案5】:

        您可以编写一个计算属性并让它根据大小写返回一个布尔值

        enum MyEnum {
          case a
          case b(Int)
          case c
        
         var isCaseB: Bool {
             switch self {
               case .b(_):
                 return true
               default:
                 return false
               }
            }
         }
        

        然后在您的代码中彻底检查:

        if !enumVal.isCaseB {
        
        }
        

        我检查了您在问题中提到的答案,但我不确定您的意思是根本不想使用 switch 语句,还是只是不想将其与其他代码混合使用。我认为这是一种在编写您需要根据具体情况执行的任何实现之前进行检查的好方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-19
          • 2010-10-13
          • 2016-10-03
          • 1970-01-01
          • 2013-12-01
          • 2012-02-16
          • 1970-01-01
          • 2011-12-21
          相关资源
          最近更新 更多