Dart 2.17+增强枚举如何处理后续新增的未知枚举值
Dart增强枚举处理未知硬件数值方案
问题1:更简洁的未知枚举值处理方式
你目前实现的静态转换方法已经是Dart下的常规实践,还可以做两处优化,让代码更简洁、性能更好、维护成本更低:
- 不要用
try-catch做分支判断:异常捕获的性能开销远高于直接查表,逻辑也不直观。可以在枚举内部一次性构建值到枚举项的静态映射表,转换时直接查表,后续新增枚举项不需要手动维护映射关系:
enum BatteryLiveDataProtocol { unknown(0), rs485(1), ttl(2), canbus(3), uart(4), ; const BatteryLiveDataProtocol(this.value); final int value; // 编译后自动生成所有枚举项的数值映射,仅初始化一次 static final Map<int, BatteryLiveDataProtocol> _valueLookup = { for (final item in BatteryLiveDataProtocol.values) item.value: item }; /// 从外设读取的int值转换为枚举,未知值统一返回unknown static BatteryLiveDataProtocol fromValue(int number) => _valueLookup[number] ?? unknown; }
- 如果项目中存在大量同类需要数值转换的枚举,可以抽离公共mixin复用转换逻辑,避免每个枚举重复编写样板代码。
问题2:是否支持携带原始值的动态未知枚举项
不支持。Dart的枚举本质是编译期确定的封闭常量集合,所有枚举项必须在定义时显式声明,运行时无法动态创建新的枚举实例,和Swift等语言原生支持的未来枚举值兼容机制有本质区别。
如果需要在未知值场景下保留外设返回的真实原始int值,不需要强行使用枚举,可以用Dart 3.0及以上版本提供的sealed class(密封类)实现和枚举几乎一致的使用体验,同时支持动态携带原始值:
sealed class BatteryLiveDataProtocol { const BatteryLiveDataProtocol(); // 已知协议类型定义为常量 static const unknown = _UnknownProtocol(); static const rs485 = _KnownProtocol(1, 'rs485'); static const ttl = _KnownProtocol(2, 'ttl'); static const canbus = _KnownProtocol(3, 'canbus'); static const uart = _KnownProtocol(4, 'uart'); // 数值转换工厂 factory BatteryLiveDataProtocol.fromValue(int number) { return switch (number) { 0 => unknown, 1 => rs485, 2 => ttl, 3 => canbus, 4 => uart, // 未知值返回携带真实原始值的实例 _ => _UnknownProtocol(number) }; } } // 已知协议类型实现 class _KnownProtocol extends BatteryLiveDataProtocol { const _KnownProtocol(this.value, this.name); final int value; final String name; } // 未知协议类型实现,存储外设返回的真实int值 class _UnknownProtocol extends BatteryLiveDataProtocol { const _UnknownProtocol([this.actualValue = 0]); final int actualValue; }
使用时可以通过Dart的模式匹配做穷尽性检查,和枚举的使用体验完全一致,同时能拿到未知值的原始数据方便调试、做后续版本兼容:
void handleProtocol(BatteryLiveDataProtocol protocol) { switch (protocol) { case BatteryLiveDataProtocol.rs485: // 处理RS485逻辑 case BatteryLiveDataProtocol.ttl: // 处理TTL逻辑 case BatteryLiveDataProtocol.canbus: // 处理CAN总线逻辑 case BatteryLiveDataProtocol.uart: // 处理UART逻辑 case _UnknownProtocol(actualValue: final rawValue): print('收到未定义的协议值:$rawValue'); // 处理未知逻辑 } }
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

