c - 如何快速捕获无效的 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 示例显示了疯狂的结果:
- 4 force cast 不打印任何值(很可能是 char 4 或 0,两者都无法打印)
- 4 个开关为 MyEnum.b (1)
- 4 等同于 MyEnum.a (0)
- 4 作为 MyEnum 原始值打印 0 (MyEnum.a)
有什么办法可以迅速捕捉到这个错误?我宁愿不使用这些奇怪的结果来检测异常。
解决方案
功能名称不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
推荐阅读
- python - 如果自定义词有符号绕过过滤器,如何过滤它们
- python-3.x - 使用scrapy shell在浏览器和shell上的响应是否有不同
- laravel - laravel-5.8:为 foreach() 提供的参数无效
- excel - Excel 2016:在宏运行时使用控件表单隐藏 Excel 功能区
- google-analytics - 如何在 cookie 同意的情况下配置 gatsby-plugin-google-analytics?
- reactjs - 在反应表中操作日期
- php - 锚标记在我的 Laravel 站点中无法正常工作
- python - 创建一个循环将数据插入 postgres 数据库
- css - AngularJS Material UI,其中对话框来自单击的元素
- c# - 如何将数据从列表视图更新到 asp.net 中的数据库?