在swift 5枚举中使用@unknown默认值:如何抑制“将永远不会执行默认值”警告?

Meh*_*mar 9 enums warnings swift swift-playground swift5

假设我有如下现有代码:

enum SomeEnumCases {
  case existing
  case alreadyExisting
}

func doSomething(withEnums enumCase: SomeEnumCases) {
  switch enumCase {
  case .existing:
    print("This case was already existing")
  case .alreadyExisting:
    print("This case was already existing too...")
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果要为枚举添加新的大小写,则上面的函数将显示一个编译错误,表明切换大小写必须是详尽无遗的,并且我将被迫处理新的丢失大小写。我会在switch语句中添加第三种情况,或添加默认语句。

现在,为了处理这种无法预料的枚举案例,我想@unknown default在上面的现有函数中添加一个案例。唯一的问题是,现在这将给我警告Default will never be executed

所以问题是,我如何将来验证我的枚举,以便可以:

  1. 详尽地处理所有当前枚举的情况,并且
  2. 对未来的未知案例具有默认的处理机制,并且
  3. 仅当添加了新的案例并且这些案例必须由默认案例处理时,才显示警告。

也就是说,以下代码不应发出警告:

enum SomeEnumCases {
  case existing
  case alreadyExisting
}

func doSomething(withEnums enumCase: SomeEnumCases) {
  switch enumCase {
  case .existing:
    print("This case was already existing")
  case .alreadyExisting:
    print("This case was already existing too...")
  @unknown default: // <-- warning: Default will never be executed: should be suppressed
    print("Alright, this is something new and exciting !!")
  }
}
Run Code Online (Sandbox Code Playgroud)

但是以下代码应发出警告:

enum SomeEnumCases {
  case existing
  case alreadyExisting
  case new
}

func doSomething(withEnums enumCase: SomeEnumCases) {
  switch enumCase { // <-- warning: Switch must be exhaustive: This should stay.
  case .existing:
    print("This case was already existing")
  case .alreadyExisting:
    print("This case was already existing too...")
  @unknown default:
    print("Alright, this is something new and exciting !!")
  }
}
Run Code Online (Sandbox Code Playgroud)

是否可以通过@unknown或其他方式?

CRD*_*CRD 7

正如规范所说,警告可能会引起误解(重点已添加):

冻结枚举是一种特殊的枚举,即使在编译和发布应用程序之后,这种枚举也可能在将来获得新的枚举用例。切换非冻结枚举需要额外考虑。当图书馆的作者将枚举标记为非冻结枚举时,他们保留添加新枚举用例的权利,并且与该枚举进行交互的任何代码都必须能够处理这些将来的用例而无需重新编译。只有标准库,Apple框架的Swift叠加层以及C和Objective-C代码才能声明非冻结枚举。您在Swift中声明的枚举不能为非冻结的

因此,分支永远不会被执行,并不是SomeEnumCases用户定义的Swift枚举完全不支持该功能的原因。

在Swift 5中似乎没有受支持的方式来实现您的期望,并且有迹象表明,添加案例被视为一项重大更改,因为它可能/将破坏二进制兼容性,但是Swift是一个不断发展的目标...

  • @AdamM – 如果与正确类型的“枚举”一起使用,将不会出现警告,如果 Swift 编译器在与错误类型一起使用时发出错误以避免混淆,可能会更好。传统的枚举是由一组文字值定义的类型,在 C 系列中,这种类型很弱,可以通过添加更多文字来扩展。Swift 使用的枚举类型本质上是“标记的不相交联合”,它们存在于多种语言中,并且可以使用“enum”、“union”和“struct”的组合在 C 系列中构建。[续...] (2认同)
  • [...续] 鉴于 Swift 编译其枚举的(当前)方式,添加新案例可能会破坏现有编译代码和*现有*案例之间的二进制兼容性,因此在添加任何新案例时需要重新编译代码。这并不是说 Swift 不能支持非冻结的 Swift 风格枚举,但他们(大概)权衡了权衡并选择不支持(但 Swift 是一个不断变化的目标......) (2认同)