运算符名称

nameof 运算符将代码元素的名称作为 string 返回。抛出与方法参数相关的异常以及实现 INotifyPropertyChanged 时,这非常有用。

public string SayHello(string greeted)
{
    if (greeted == null)
        throw new ArgumentNullException(nameof(greeted));
    
    Console.WriteLine("Hello, " + greeted);
}

在编译时评估 nameof 运算符,并将表达式更改为字符串文字。这对于以公开它们的成员命名的字符串也很有用。考虑以下:

public static class Strings
{
    public const string Foo = nameof(Foo); // Rather than Foo = "Foo"
    public const string Bar = nameof(Bar); // Rather than Bar = "Bar"
}

由于 nameof 表达式是编译时常量,因此可以在属性,case 标签,switch 语句等中使用它们。

使用 nameofEnums 很方便。代替:

Console.WriteLine(Enum.One.ToString());

可以使用:

Console.WriteLine(nameof(Enum.One))

两种情况下的输出都是 One

nameof 运算符可以使用类似静态的语法访问非静态成员。而不是做:

string foo = "Foo";
string lengthName = nameof(foo.Length);

可以替换为:

string lengthName = nameof(string.Length);

两个例子中的输出都是 Length。但是,后者可以防止创建不必要的实例。

虽然 nameof 运算符适用于大多数语言结构,但存在一些限制。例如,你不能在开放泛型类型或方法返回值上使用 nameof 运算符:

public static int Main()
{   
    Console.WriteLine(nameof(List<>)); // Compile-time error
    Console.WriteLine(nameof(Main())); // Compile-time error
}

此外,如果将其应用于泛型类型,则将忽略泛型类型参数:

Console.WriteLine(nameof(List<int>));  // "List"
Console.WriteLine(nameof(List<bool>)); // "List"

有关更多示例,请参阅专用于 nameof此主题

以前版本的解决方法(更多细节

虽然对于 6.0 之前的版本,在 C#中不存在 nameof 运算符,但是使用 MemberExpression 可以获得类似的功能,如下所示:

Version < 6

表达:

public static string NameOf<T>(Expression<Func<T>> propExp)
{
    var memberExpression = propExp.Body as MemberExpression;
    return memberExpression != null ? memberExpression.Member.Name : null;
}

public static string NameOf<TObj, T>(Expression<Func<TObj, T>> propExp)
{
    var memberExpression = propExp.Body as MemberExpression;
    return memberExpression != null ? memberExpression.Member.Name : null;
}

用法:

string variableName = NameOf(() => variable);
string propertyName = NameOf((Foo o) => o.Bar);

请注意,这种方法会导致在每次调用时创建表达式树,因此与在编译时计算并且在运行时没有开销的 nameof 运算符相比,性能要差得多。