運算子名稱

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 運算子相比,效能要差得多。