在我的程序中,我表示了一些对象字段的更改历史,如下所示:
struct FieldChange {
property_name: &'static str,
// some other fields
}
let history = Vec<FieldChange>::new();
我是这样处理的:
match field_change.property_name {
"name" => // do something,
"age" => // do something,
_ => {}
}
为了提高可读性和便于以后的重构,我想这样写:
match field_change.property_name {
nameof(Person::name) => // do something,
nameof(Person::age) => // do something,
_ => {}
}
其中nameof
生成字段的&str
表示,类似于c#中的nameof
。
我正在寻找的要点是,编译器可以验证字段是否存在(例如,在这种情况下,Person
是否确实具有name
和age
字段)。在Rust中可以像这样提取字段名吗?
不,但是您可以使用宏获得类似的东西。因为宏解决了所有的问题!<一口>[1]一口>
macro_rules! name_of {
($name:ident in $ty:ty) => {
{
#[allow(dead_code)]
fn dummy(v: $ty) {
let _ = &v.$name;
}
stringify!($name)
}
};
($name:ident) => {
{
let _ = &$name;
stringify!($name)
}
};
}
struct Person {
// 255 years should be enough for anybody.
age: u8,
name: String,
}
fn main() {
let p = Person { age: 27, name: "John Smith".into() };
println!("The {} of Person {} is: {}", name_of!(age in Person), name_of!(p), p.age);
}
如果您尝试使用一个不存在的名称,您将得到如下所示的内容:
error: unresolved name `q`. Did you mean `p`? [--explain E0425]
--> <anon>:28:78
28 |> println!("The {} of Person {} is: {}", name_of!(age in Person), name_of!(q), p.age);
|> ^
或者像这样:
error: attempted access of field `shoe_size` on type `Person`, but no field with that name was found
--> <anon>:6:26
6 |> let _ = &v.$name;
|> ^
[1]:注意:宏实际上并不能解决所有问题。