在Rust中是否有类似于c#的nameof() ?



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

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是否确实具有nameage字段)。在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]:注意:宏实际上并不能解决所有问题。

相关内容

  • 没有找到相关文章

最新更新