Operator nameof
suggest changeThe nameof
operator returns the name of a code element as a string
. This is useful when throwing exceptions related to method arguments and also when implementing INotifyPropertyChanged
.
public string SayHello(string greeted)
{
if (greeted == null)
throw new ArgumentNullException(nameof(greeted));
Console.WriteLine("Hello, " + greeted);
}
The nameof
operator is evaluated at compile time and changes the expression into a string literal. This is also useful for strings that are named after their member that exposes them. Consider the following:
public static class Strings
{
public const string Foo = nameof(Foo); // Rather than Foo = "Foo"
public const string Bar = nameof(Bar); // Rather than Bar = "Bar"
}
Since nameof
expressions are compile-time constants, they can be used in attributes, case
labels, switch
statements, and so on.
It is convenient to use nameof
with Enum
s. Instead of:
Console.WriteLine(Enum.One.ToString());
it is possible to use:
Console.WriteLine(nameof(Enum.One))
The output will be One
in both cases.
The nameof
operator can access non-static members using static-like syntax. Instead of doing:
string foo = "Foo";
string lengthName = nameof(foo.Length);
Can be replaced with:
string lengthName = nameof(string.Length);
The output will be Length
in both examples. However, the latter prevents the creation of unnecessary instances.
Although the nameof
operator works with most language constructs, there are some limitations. For example, you cannot use the nameof
operator on open generic types or method return values:
public static int Main()
{
Console.WriteLine(nameof(List<>)); // Compile-time error
Console.WriteLine(nameof(Main())); // Compile-time error
}
Furthermore, if you apply it to a generic type, the generic type parameter will be ignored:
Console.WriteLine(nameof(List<int>)); // "List"
Console.WriteLine(nameof(List<bool>)); // "List"
For more examples, see this topic dedicated to nameof
.
Workaround for previous versions (more detail)
Although the nameof
operator does not exist in C# for versions prior to 6.0, similar functionality can be had by using MemberExpression
as in the following:
Expression:
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;
}
Usage:
string variableName = NameOf(() => variable);
string propertyName = NameOf((Foo o) => o.Bar);
Note that this approach causes an expression tree to be created on every call, so the performance is much worse compared to nameof
operator which is evaluated at compile time and has zero overhead at runtime.