
回复
作为一个曾在枚举设计中踩过坑的开发者,第一次因为枚举设计混乱导致代码维护噩梦,花了三天重构。今天把这些年总结的枚举与模式匹配最佳实践分享出来,让代码像诗歌一样整洁易读。
每个枚举只表达一个概念,就像工具盒里的工具各有专用:
反例(混乱枚举):
// 反例:混合网络状态与错误类型
enum NetworkStatus {
| Connected | Disconnected | Timeout(ms: Int) | Error(code: Int)
}
正例(职责分离):
// 网络连接状态
enum NetworkState { | Connected | Disconnected }
// 网络错误类型
enum NetworkError { | Timeout(ms: Int) | CodeError(code: Int) }
重构收益:
给构造器参数加上具名标签,比注释更可靠:
// 坐标枚举(语义化参数)
enum Point {
| TwoD(x: Double, y: Double)
| ThreeD(x: Double, y: Double, z: Double)
}
// 使用时明确参数含义
let point = Point.TwoD(x: 3.0, y: 4.0)
实战技巧:
.Connected
).Timeout(ms:)
)把高频操作放在匹配分支顶部,就像把常用工具放在工具箱最外层:
enum UserAction {
| Click | DoubleClick | LongPress(duration: Int)
}
func handleAction(action: UserAction) {
match action {
case .Click => handleClick() // 高频操作优先
case .DoubleClick => handleDouble()
case .LongPress(d) => handleLongPress(d)
}
}
性能数据:
永远用_
处理未预期情况,避免运行时崩溃:
enum HttpMethod { | GET | POST | PUT | DELETE }
func processMethod(method: HttpMethod) {
match method {
case .GET => fetchData()
case .POST => submitData()
case .PUT => updateData()
case .DELETE => deleteData()
case _ => error("不支持的方法") // 兜底处理未来新增方法
}
}
血泪教训:
曾因未处理新增的.PATCH
方法导致线上崩溃,加入通配符后此类问题清零
用Result<T, E>
替代bool
返回值,类型系统帮你检查错误路径:
enum FileError { | NotFound | PermissionDenied }
func readConfig() -> Result<String, FileError> {
if !fileExists("config.json") {
return .Err(.NotFound)
}
if !hasReadPermission() {
return .Err(.PermissionDenied)
}
return .Ok(readFileContent())
}
// 调用处强制处理错误
match readConfig() {
case .Ok(content) => process(content)
case .Err(error) => showError(error)
}
优势对比:
方案 | 类型安全 | 错误路径 | 代码可读性 |
---|---|---|---|
bool返回 | ❌ | 需文档 | 差 |
Result枚举 | ✅ | 强制处理 | 优 |
用枚举替代int
类型的状态码,代码自己会说话:
反例(魔法值):
let status = 2 // 0=正常,1=警告,2=错误(靠注释理解)
正例(枚举):
enum SystemStatus { | Normal | Warning | Error }
let status = SystemStatus.Error
重构效果:
无参枚举仅占1字节,适合纯状态标识,如开关状态:
enum ConnectionState { | Connected | Disconnected | Connecting } // 无参枚举
内存对比:
利用编译器强制覆盖所有枚举情况,避免逻辑漏洞:
enum Color { | Red | Green | Blue }
func printColorName(color: Color) {
match color {
case .Red => print("红")
case .Green => print("绿")
// 编译错误:未处理.Blue,强制补充逻辑
}
}
实践技巧:
@exhaustive
注解显式标记穷尽匹配// 设备类型枚举
enum DeviceType { | Light | Lock | Sensor }
// 控制命令枚举(单一职责)
enum ControlCommand {
| TurnOn | TurnOff
| SetBrightness(level: Int)
| SetSecurityMode(mode: SecurityMode)
}
// 安全模式枚举
enum SecurityMode { | Normal | Alert | Disarm }
func sendCommand(device: DeviceType, cmd: ControlCommand) {
match device {
case .Light:
match cmd { // 第二层匹配,逻辑集中
case .TurnOn => sendLightCmd("on")
case .TurnOff => sendLightCmd("off")
case .SetBrightness(l) => sendLightCmd("brightness=\(l)")
case .SetSecurityMode(_) => error("灯光不支持安全模式")
}
case .Lock:
match cmd {
case .SetSecurityMode(m) => sendLockCmd("mode=\(m)")
// 其他命令处理...
}
case .Sensor:
// 传感器命令处理...
}
}
func sendLightCmd(cmd: String) -> Result<Bool, LightError> {
if isLightConnected() {
return .Ok(writeToLight(cmd))
} else {
return .Err(.NotConnected)
}
}
enum LightError { | NotConnected | CommandFailed }
.SetBrightness
)而非动词