首页 > 解决方案 > 如何快速捕获无效的 c 枚举

问题描述

我使用 C 来转换我的无线有效负载,因此在 c 中将 int 转换为枚举:

typedef CF_ENUM( uint8_t, MyEnum_t ) {
    a = 0
    b = 1
}
...
value = ( MyEnum_t * ) rawValue;

因为该值是通过网络传输的,所以实际的原始值可以是任何 uint8_t。有可能rawValue实际上不是 0 或 1。

下面我有一个快速代码示例,显示将枚举设置为不可能/无效的值以及处理该值的 switch 语句。

import Foundation

enum MyEnum: UInt8 {
    case a = 0
    case b = 1
}

let raw: UInt8 = 0b100 // 4
let value: MyEnum = unsafeBitCast(raw, to: MyEnum.self)

switch value {
case .a:
    print("a:", value) // * not reached *
case .b:
    print("b:", value) // "b: \n"
    print("value == .a => \(value == .a)") // "x == .a => true\n"
    print("value == .b => \(value == .b)") // "x == .b => false\n"
}

print(value.rawValue) // "0"

C 原始值为 4 时,swift 示例显示了疯狂的结果:

有什么办法可以迅速捕捉到这个错误?我宁愿不使用这些奇怪的结果来检测异常。

标签: cswiftcore-foundation

解决方案


功能名称不unsafeBitCast言自明。此外,文档清楚地表明:

警告调用这个函数会破坏 Swift 类型系统的保证;小心使用。

你绝对不应该像这样依赖 Swift 中的内部枚举实现,因为它可能会改变。您应该以标准方式处理特殊情况。也许,您可以添加一个自定义初始化程序:

import Foundation

enum MyEnum: UInt8 {
    case a = 0
    case b = 1

    init(fromWire value: UInt8) {                  // handle unusual input here
            self = value == 0 ? .a : .b
    }
}

// Test how it works
let arr: [UInt8] = [0, 1, 4]
for raw in arr {
    print("Input:", raw)
    let value = MyEnum(fromWire: raw)
    print("Value: \(value), raw enum value: \(value.rawValue)")
    if value==MyEnum.a { print("value == .a") }
    if value==MyEnum.b { print("value == .b") }
    switch value {
    case .a: print("case .a")
    case .b: print("case .b")
    }
    print()
}

输出:

Input: 0
Value: a, raw enum value: 0
value == .a
case .a

Input: 1
Value: b, raw enum value: 1
value == .b
case .b

Input: 4
Value: b, raw enum value: 1
value == .b
case .b

推荐阅读