多种选择:枚举与匹配
原理
Rust 的 enum 是带标签的联合体(tagged union / sum type)。编译器在内部存储为:一个 discriminants(标签,通常是一个整数,取最小所需位数)+ 一个变体数据的 union。对于无数据变体,discriminants 本身足够。
match 在编译期做穷尽性检查(exhaustiveness checking)。编译器构建决策树(decision tree),为每个模式生成对应的跳转指令。对简单枚举,编译后等价于 switch 语句;对复杂模式,生成嵌套的条件分支。
Option<T> 是一个大小等于 max(sizeof(T), 0) + discriminants 的类型。None 没有运行时代价(使用特殊的 discriminants 值或 niche optimization)。例如 Option<bool> 占用 1 字节(而非 2 字节),因为 bool 只用 0/1,剩余空间可编码 None。
match 守卫(if n > 5)在模式匹配之后执行,不改变穷尽性检查的范围。
语法
定义
enum TrafficLight {
Red, // 无数据
Yellow,
Green,
}
enum Message {
Quit,
Move { x: i32, y: i32 }, // 带命名字段
Write(String), // 带元组数据
ChangeColor(i32, i32, i32),
}match 穷尽匹配
let light = TrafficLight::Red;
match light {
TrafficLight::Red => "stop",
TrafficLight::Yellow => "slow",
TrafficLight::Green => "go",
// 编译器强制穷尽所有变体
}match msg {
Message::Quit => { },
Message::Move { x, y } => println!("({},{})", x, y),
Message::Write(text) => println!("{}", text),
Message::ChangeColor(r, g, b) => println!("{},{},{}", r, g, b),
}Option
enum Option<T> { Some(T), None }
let x: Option<i32> = Some(5);
// let y = x + 1; // 错误:Option<i32> != i32
let y = match x {
Some(n) => n + 1,
None => 0,
};
// 快捷方法
x.unwrap(); // panic on None
x.unwrap_or(0); // None 时返回默认
x.is_some();
x.is_none();if let — 单分支 match 简写
if let Some(n) = x {
println!("有值:{}", n);
} else {
println!("无值");
}通配符 _ 和守卫
match n {
1 => "one",
2..=9 => "small",
_ => "other", // 匹配一切
}
match opt {
Some(n) if n > 0 => "正数",
Some(_) => "非正数",
None => "无",
}为枚举实现方法
impl TrafficLight {
fn duration(&self) -> u32 {
match self {
Self::Red => 60,
Self::Yellow => 5,
Self::Green => 45,
}
}
}实践
力扣问题
力扣: 力扣状态机题 — 状态机模式
enum State { Playing, Paused, Over }力扣: 力扣数组计数题 — match 分支
AI 自检
Option<bool>占用几个字节?解释 niche optimization 原理。match和if let在编译后的控制流图有什么区别?