如何在Rust中向枚举写入值后安全获取对应字段的可变引用
解决方案
方案1:使用 let-else 语句(Rust 1.65+,最推荐)
这是目前最简洁的安全实现,语义清晰,仅需一行代码完成分支判断,虽然依然用到unreachable!,但写法远比完整的match块紧凑,所有阅读者都能一眼识别该分支是逻辑上的不可达分支:
impl State { fn wake_up(&mut self) -> &mut Vec<String> { *self = Self::Awake { deeds: vec![] }; let Self::Awake { deeds } = self else { unreachable!() }; deeds } }
方案2:封装变体取值方法,完全避免手写unreachable!
你可以为枚举实现通用的变体取值方法,后续所有需要提取字段的场景都可以复用,wake_up方法中仅需调用unwrap即可:
impl State { // 通用的Awake变体可变引用提取方法 fn as_awake_mut(&mut self) -> Option<&mut Vec<String>> { match self { Self::Awake { deeds } => Some(deeds), _ => None } } fn wake_up(&mut self) -> &mut Vec<String> { *self = Self::Awake { deeds: vec![] }; // 因为上一行刚赋值为Awake变体,unwrap必然成功 self.as_awake_mut().unwrap() } }
方案3:使用不可达提示优化性能(unsafe)
如果你追求极致性能,可以使用编译器内置的不可达提示,会直接裁剪掉不可能的分支,无任何运行时开销,但需要你自行保证逻辑正确性:
use std::hint::unreachable_unchecked; impl State { fn wake_up(&mut self) -> &mut Vec<String> { *self = Self::Awake { deeds: vec![] }; match self { Self::Awake { deeds } => deeds, _ => unsafe { unreachable_unchecked() } } } }
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

