带有浮点原始值的 Swift 枚举的“枚举大小写的原始值不是唯一的”

Posted

技术标签:

【中文标题】带有浮点原始值的 Swift 枚举的“枚举大小写的原始值不是唯一的”【英文标题】:"Raw value for enum case is not unique" for Swift enum with Float raw values 【发布时间】:2014-11-04 16:12:35 【问题描述】:

根据The Swift Programming Language,我应该能够使用“字符串、字符或任何整数或浮点数类型”的原始值创建一个 Swift 枚举。但是当我尝试时:

enum BatteryVoltage: Float 
    case v3v7 = 3.7
    case v5v0 = 5.0
    case v7v4 = 7.4
    case v11v1 = 11.1
    case v12v0 = 12.0

...我得到一个编译错误:

Raw value for enum case is not unique

在 v7v4 线上。它与注释掉的那个编译得很好。但是啊,它看起来对我来说很独特。如果我将值设为 7.41、7.3 或其他值,它编译得很好。这是怎么回事? Swift 错误?

【问题讨论】:

这看起来绝对像一个错误。如果一个枚举值恰好等于“另一个枚举值的 2 倍”(但不是整数),这似乎会发生。 你知道吗,你是对的。回答您的评论,我会接受。 (并归档雷达。叹息。) 我猜这可能与浮点数的二进制表示有关。也许枚举的相等比较会截断一些位。 雷达归档,rdar://18878723 现在在 Swfit 2 中,这不是错误。 【参考方案1】:

它肯定说你可以,但不要使用浮点值(尤其是Float),因为你需要比较相等性——精度不是保证足够好。并且始终使用Double,除非出于兼容性原因绝对需要使用Float

在这种情况下,它似乎遇到了麻烦,因为 (a) 第三种情况是第一种情况的 2 倍,以及 (b) 其他一些我不知道的因素。使用3.3/6.63.4/6.83.6/7.2 也给了我这个问题,但3.5/7.0 没有。但是,我可以通过将最后一个大小写更改为 22.2 (2x 11.1) 来显示它。

这是一种解决方法 - 使用典型的基于 Int 的枚举,并提供 doubleValue 属性:

enum BatteryVoltage: Int 
    case v3v7
    case v5v0
    case v7v4
    case v11v1
    case v12v0

    var doubleValue: Double 
        switch self 
        case .v3v7: return 3.7
        case .v5v0: return 5.0
        case .v7v4: return 7.4
        case .v11v1: return 11.1
        case .v12v0: return 12.0
        
    

如果它们是基于Int 的,您可以利用一些nice additional features of enums。

【讨论】:

我给你这个博客文章链接 - 向枚举添加一个使用 Int 值索引到值数组的方法是实现我想做的更好的方法.【参考方案2】:

(来自我上面的评论:)

这看起来绝对像一个错误。如果一个枚举值恰好等于“另一个枚举值的 2 倍”,但不等于整数,这似乎会发生。

更一般地(正如@Sulthan 观察到的)如果枚举的比率发生错误 values 是 2 的幂,例如 3.7/7.41.2/4.81.1/17.6,但只有 如果两个值都具有非零小数部分。所以1.5/3.01.25/5.0 不要 导致错误。

【讨论】:

@Sulthan:你是对的,不仅因素 2 会导致问题,还有 4、8、16、...【参考方案3】:

对我来说这是可行的。

我将空字符串分配给枚举中的多个 case 值。我改变了那个。确保每个 case 值都是唯一的。

【讨论】:

以上是关于带有浮点原始值的 Swift 枚举的“枚举大小写的原始值不是唯一的”的主要内容,如果未能解决你的问题,请参考以下文章

Swift:枚举编码如何获取原始值[重复]

在核心数据中保存没有原始值的快速枚举

Swift枚举使用String值获取Int Enum的值

Swift 学习- 09 -- 枚举

通过扩展自动合成 Swift 结构或枚举的 Equatable 一致性

如何在 Objective-C 中使用 Swift 字符串枚举?