是否可以在枚举关联值条件和另一个枚举案例之间编写复合开关案例?

Posted

技术标签:

【中文标题】是否可以在枚举关联值条件和另一个枚举案例之间编写复合开关案例?【英文标题】:Is it possible to write compound switch case between enum associated value conditional and another enum case? 【发布时间】:2019-06-06 17:06:55 【问题描述】:

出于演示目的,我创建了下一个代码:

enum WeatherType 
    case cloudy(coverage: Int)
    case sunny
    case rainy


let today: WeatherType = .cloudy(coverage: 0)

switch today 
case .cloudy(let coverage) where coverage == 0, .sunny:   // <-- This line doesn't compile
    print("☀️")
case .cloudy(let coverage) where 1...100 ~= coverage:
    print("☁️")
case .rainy:
    print("????")
default:
    print("Unknown weather")


编译错误消息是'coverage' must be bound in every pattern。正如我已经用谷歌搜索过的那样,使用关联值的一种方法是比较同一枚举案例中值的不同状态。但这可能会导致代码重复,例如在我的示例中,我需要为.sunny.cloudy(let coverage) where coverage == 0 编写两个case 语句。

有没有正确、快捷的方式来处理此类案件?

【问题讨论】:

覆盖率为 0 的云在您的数据模型中应该是无效的。一旦它成为非法值,您就不必担心到处处理它。 感谢您的评论,但这是仅为演示目的创建的代码,只是为了了解开关/案例功能。 【参考方案1】:

您不需要 where 子句来匹配 .cloudy(coverage: 0),只需

case .cloudy(coverage: 0), .sunny: 
    print("☀️")

另一种选择是使用fallthrough,例如

case .cloudy(let coverage) where coverage < 10:
    fallthrough
case .sunny:
    print("☀️")

【讨论】:

与本次问答有些相关:***.com/q/41251872/4573247【参考方案2】:

马丁是对的 (+1)。

但我可能会建议进一步改进,将您的 switch 移动到 WeatherType 的扩展名(我可能只是称之为 Weather),这样您就不必重复此 switch 声明每次您在寻找符号时:

enum Weather 
    case cloudy(Int)
    case sunny
    case rainy


extension Weather 
    var symbol: String 
        switch self 
        case .cloudy(0), .sunny:
            return "☀️"
        case .cloudy:
            return "☁️"
        case .rainy:
            return "?"
        
    

那么你可以这样做:

let today: Weather = .cloudy(0)
print(today.symbol)

即使您想将小于 10 的任何事物视为晴天,您仍然不需要 where 子句:

extension Weather 
    var symbol: String 
        switch self 
        case .cloudy(..<10), .sunny:
            return "☀️"
        case .cloudy:
            return "☁️"
        case .rainy:
            return "?"
        
    

【讨论】:

甚至可以使用部分范围:case .cloudy(..&lt;10) 太棒了!感谢您分享有关扩展和范围简写语法的想法!【参考方案3】:

模式匹配是可组合的,因此您可以这样做:

switch today 
case .sunny, .cloudy(0):
    print("☀️")
case .cloudy(1...10):
    print("☁️")
case .rainy:
    print("?")
default:
    print("Unknown weather")

【讨论】:

case .cloudy(1...10): 没有哪里——那更好! @MartinR 仍然不完美。 .cloudy(0) 应该是非法状态,否则会在整个应用逻辑中弹出。我会制作一个结构包装器,它公开一个初始化程序,确保使用.sunny 而不是.cloudy(0)

以上是关于是否可以在枚举关联值条件和另一个枚举案例之间编写复合开关案例?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用“@available”将具有关联值的枚举案例标记为可能不可用

如何将枚举案例传递给使用“if case”检查属性案例的函数

是否可以在 C# 中限制公共枚举值?

是否可以为JPA编写通用枚举转换器?

Swift 枚举

Rails:在模型之间共享枚举声明值