【问题标题】:Unwrap enum when all variants are of the same type当所有变体都属于同一类型时,解包枚举
【发布时间】:2019-08-09 22:32:59
【问题描述】:

考虑这样的枚举定义:

enum Money {
    USD(u32),
    EUR(u32),
    CHF(u32),
    // many more...
}

请注意,所有枚举变体的类型均为 u32

fn amount(money: Money) -> u32 {
    // ?
}

我是否可以在不匹配所有情况的情况下一般提取 Money 实例中包含的包装 u32,如果可以,如何?

【问题讨论】:

  • 如果这是您的类型的属性,您可以考虑重新设计它:将enum Currency { Usd, Eur, Chf, ...}struct Money { currency: Currency, quantity: u32 } 结合起来
  • 这个用例的中心是一个糟糕的数据建模。当然这是一个示例,但重要的原因是,如果您的数据被正确建模,您不会经常(从不?)需要这样的访问器。
  • 你可以做unsafe {(std::mem::transmute_copy::<Money, u64>(self)>>32) as u32}。告诉别人你在哪里找到的。
  • 我相信在这里使用transmute_copy 会调用未定义的行为,因为枚举的布局是未定义的。如果不出意外,它假定判别式出现在值之前,这是无法保证的。我强烈建议不要使用它。
  • 如果仍有疑问:unsafe 技巧可以被视为一个笑话或作为枚举编码方式的演示,但 不是 作为正确的 sn -p 你应该粘贴到你的代码中。

标签: enums rust


【解决方案1】:

不幸的是,没有内置的方法可以做到这一点。通常的做法是创建一个访问器方法:

impl Money {
    pub fn amount(&self) -> u32 {
        match *self {
            Money::USD(amount) => amount,
            Money::EUR(amount) => amount,
            Money::CHF(amount) => amount,
        }
    }
}

至少这样你只需要做一次。

【讨论】:

  • 但是恕我直言,这违背了拥有Money 枚举的目的,因为您在完全不了解货币的情况下得到了一个普通的u32。可以,不知道好不好:/
  • @hellow 我倾向于同意。 trentcl 也对有关设计的问题做出了相关评论。
  • 请注意,也可以写成Money::USD(amount)|Money::CHF(amount)|Money::EUR(amount) => amount(我不假装它更好,但它不那么冗长)
猜你喜欢
  • 2015-08-21
  • 2016-04-29
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 2014-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多