Rust中的C#是否有类似名称()?

时间:2016-08-18 08:35:48

标签: reflection rust

在我的程序中,我代表了一些对象字段更改的历史记录,如下所示:

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是否确实有nameage字段)。是否可以在Rust中提取这样的字段名称?

1 个答案:

答案 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]:注意:宏实际上并不能解决所有问题。