在我的程序中,我代表了一些对象字段更改的历史记录,如下所示:
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
表示,类似于nameof
in C#。
我正在寻找的主要观点是,编译器可以验证字段是否存在(例如,在这种情况下,Person
是否确实有name
和age
字段)。是否可以在Rust中提取这样的字段名称?
答案 0 :(得分:3)
不,但你可以获得与宏相似的东西。因为宏解决了所有事情! [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]:注意:宏实际上并不能解决所有问题。