運算子名稱
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
語句等中使用它們。
使用 nameof
和 Enum
s 很方便。代替:
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
運算子相比,效能要差得多。