在Rust中具有常量值的枚举

アレッ*_*ックス 28 rust

我可以做这个:

enum MyEnum {
    A(i32),
    B(i32),
}
Run Code Online (Sandbox Code Playgroud)

但不是这个:

enum MyEnum {
    A(123), // 123 is a constant
    B(456), // 456 is a constant
}
Run Code Online (Sandbox Code Playgroud)

我可以创建结构的AB用单场,然后执行该领域,但我觉得可能是一个更简单的方法.有没有?

huo*_*uon 45

回答这个的最好方法是找出为什么你想在枚举中使用常量:你只是将一个值与每个变量相关联,或者你是否希望每个变量都是那个值(比如enum在C或C++中)?

对于第一种情况,将枚举变体保留为无数据可能更有意义,并创建一个函数:

enum MyEnum {
    A,
    B,
}

impl MyEnum {
    fn value(&self) -> i32 {
        match *self {
            MyEnum::A => 123,
            MyEnum::B => 456,
        }
    }
}
// call like some_myenum_value.value()
Run Code Online (Sandbox Code Playgroud)

这种方法可以多次应用,将许多单独的信息与每个变体相关联,例如,您可能也想要一种.name() -> &'static str方法.

或者,对于第二种情况,您可以像C/C++一样分配显式标记值:

enum MyEnum {
    A = 123,
    B = 456,
}
Run Code Online (Sandbox Code Playgroud)

这可以以match相同的方式编辑,但也可以转换为整数MyEnum::A as i32.(请注意,类似计算MyEnum::A | MyEnum::B在Rust中不会自动合法:枚举具有特定值,它们不是位标志.)

  • 如何匹配值(在“value”函数中实现)? (3认同)

Val*_*tin 14

创建具有常量值的“枚举”,可以使用结构和相关常量进行扩充。这类似于像bitflags这样的 crate 的工作方式以及它会生成什么。

此外,为了防止直接实例化,MyEnum您可以使用#[non_exhaustive].

#[non_exhaustive]
struct MyEnum;

impl MyEnum {
    pub const A: i32 = 123;
    pub const B: i32 = 456;
}
Run Code Online (Sandbox Code Playgroud)

然后,您只需像其他方式一样使用“枚举”,通过访问MyEnum::AMyEnum::B

  • 您可以迭代这里的每个变体吗? (3认同)

use*_*968 6

看到这个的人可能会偶然发现FromPrimitive. 一个可能在这里也有用的替代品是enum_primitive。它允许您使用类似 C 的枚举并让它们在数字和逻辑表示之间进行转换:

#[macro_use]
extern crate enum_primitive;
extern crate num;

use num::FromPrimitive;

enum_from_primitive! {
    #[derive(Debug, PartialEq)]
    enum FooBar {
        Foo = 17,
        Bar = 42,
        Baz,
    }
}

fn main() {
    assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
    assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
    assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
    assert_eq!(FooBar::from_i32(91), None);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这个怎么样?

enum MyEnum {
    A = 123,
    B = 456,
}

assert_eq!(MyEnum::A as i32, 123i32);
assert_eq!(MyEnum::B as i32, 456i32);
Run Code Online (Sandbox Code Playgroud)