我可以这样做:
enum MyEnum {
A(i32),
B(i32),
}
但不是这样:
enum MyEnum {
A(123), // 123 is a constant
B(456), // 456 is a constant
}
我可以使用单个字段为A
和B
创建结构,然后实现该字段,但我认为可能有一种更简单的方法。有没有?
答案 0 :(得分:35)
回答这个问题的最好方法是找出为什么你想要枚举中的常量:你只是将一个值与每个变体相关联,或者你是否希望每个变体 该值(如C或C ++中的enum
)?
对于第一种情况,将枚举变量保留为无数据可能更有意义,并且可以创建一个函数:
enum MyEnum {
A,
B,
}
impl MyEnum {
fn value(&self) -> i32 {
match *self {
MyEnum::A => 123,
MyEnum::B => 456,
}
}
}
// call like some_myenum_value.value()
这种方法可以多次应用,以将许多单独的信息与每个变体相关联,例如,也许你也想要一个.name() -> &'static str
方法。
或者,对于第二种情况,您可以像C / C ++一样分配显式标记值:
enum MyEnum {
A = 123,
B = 456,
}
这可以match
以相同的方式进行,但也可以强制转换为整数MyEnum::A as i32
。 (请注意,像MyEnum::A | MyEnum::B
这样的计算在Rust中不会自动合法:枚举具有特定值,它们不是位标志。)
答案 1 :(得分:5)
可以使用结构和associated constants来增强创建具有恒定值的“枚举”。 这类似于bitflags这样的板条箱的工作方式以及产生的结果。
另外,要防止直接实例化MyEnum
,可以用#[non_exhaustive]
对其进行标记。
#[non_exhaustive]
struct MyEnum;
impl MyEnum {
pub const A: i32 = 123;
pub const B: i32 = 456;
}
然后,您可以通过访问MyEnum::A
和MyEnum::B
来简单地使用“枚举”。
答案 2 :(得分:3)
关注这一点的人可能偶然发现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);
}
答案 3 :(得分:1)
另一种选择是enum-map条板箱。这样就可以为枚举记录分配值。而且,您可以将此宏用于不同的值类型。
#[macro_use]
extern crate enum_map;
use enum_map::EnumMap;
#[derive(Debug, Enum)]
enum Example {
A,
B,
C,
}
fn main() {
let mut map = enum_map! {
Example::A => 1,
Example::B => 2,
Example::C => 3,
};
map[Example::C] = 4;
assert_eq!(map[Example::A], 1);
for (key, &value) in &map {
println!("{:?} has {} as value.", key, value);
}
}