Rust 中有 C# 中的 nameof() 类似吗?

xil*_*lec 8 reflection rust

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

struct FieldChange {
    property_name: &'static str,
    // some other fields
}

let history = Vec<FieldChange>::new();
Run Code Online (Sandbox Code Playgroud)

我这样处理:

match field_change.property_name {
    "name" => // do something,
    "age"  => // do something,
    _      => {}
}
Run Code Online (Sandbox Code Playgroud)

为了提高可读性并方便将来的重构,我想写这样的内容:

match field_change.property_name {
    nameof(Person::name) => // do something,
    nameof(Person::age)  => // do something,
    _                    => {}
}
Run Code Online (Sandbox Code Playgroud)

wherenameof生成&str字段的表示,类似于nameofC# 中的

我正在寻找的要点是编译器可以验证字段是否存在(例如,在本例中,是否Person确实有nameage字段)。在 Rust 中是否可以像这样提取字段名称?

DK.*_*DK. 7

不,但你可以获得与宏类似的东西。因为宏可以解决一切! [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);
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试使用不存在的名称,您会得到如下所示的内容:

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);
}
Run Code Online (Sandbox Code Playgroud)

或者像这样:

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);
   |>                                                                              ^
Run Code Online (Sandbox Code Playgroud)

[1]:注意:宏实际上并不能解决所有问题。