What is the purpose of nameof?
What about cases where you want to reuse the name of a property, for example when throwing exception based on a property name, or handling a PropertyChanged
event. There are numerous cases where you would want to have the name of the property.
Take this example:
switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; }
// opposed to
case "SomeOtherProperty":
{ break; }
}
In the first case, renaming SomeProperty
will cause a compilation error if you don't change both the property definition and the nameof(SomeProperty)
expression. In the second case, renaming SomeOtherProperty
or altering the "SomeOtherProperty"
string will result in silently broken runtime behavior, with no error or warning at build time.
This is a very useful way to keep your code compiling and bug free (sort-of).
(A very nice article from Eric Lippert why infoof
didn't make it, while nameof
did)
How does nameof work?
It's not "accessing" the property - that operator is purely a compiler mechanism to inject the "name" of the argument into the code. In this case it will replace nameof(TestClass.Name)
with "Name"
. The fact that it's non-static is irrelevant.
nameof() operator for static string
nameof
is an operator that is evaluated at compile time, so once your application is compiled there is actually no difference between those two solutions.
However, using nameof
in this case has a few benefits:
- It makes the string value less “magic”. So instead of being some disconnected magic string, the semantic reasoning behind that value is very clear: It’s the name of the variable itself.
- The name is an actual reference to the name, so they are both connected. This allows you to refactor either of them and automatically affect the other one. It also makes that “string” appear as a reference when looking up references to that variable. So you know exactly where it has been used.
nameof equivalent in Java
Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.
See Get name of a field
You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.
Difference between nameof and typeof
Two reasons:
nameof
turns into a compile-time constant. typeof(...).Name
requires a bit of reflection. It's not overly expensive, but it can hurt in some cases.
Second, it's used for other things than type names. For example, arguments:
void SomeMethod(int myArgument)
{
Debug.WriteLine(nameof(myArgument));
}
You can also get the name of class members and even locals. Needless to say, this is quite useful for debugging information. It's also one of the ways to implement less fragile reflection when e.g. parsing expression trees (sadly, on the project where I'd use this, we're still stuck on .NET 4.0 with C# 5 - it'd save me a few hacks here and there).
And to clear up some confusion, nameof
is not a function, and neither is typeof
. It's a compile-time operator, and it's always evaluated at compile-time (though obviously, generics move the "compile-time" a bit further in time).
Is nameof() evaluated at compile-time?
Yes. nameof()
is evaluated at compile-time. Looking at the latest version of the specs:
The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).
From nameof operator - v5
You can see that with this TryRoslyn example where this:
public class Foo
{
public void Bar()
{
Console.WriteLine(nameof(Foo));
}
}
Is compiled and decompiled into this:
public class Foo
{
public void Bar()
{
Console.WriteLine("Foo");
}
}
Its run-time equivalent is:
public class Foo
{
public void Bar()
{
Console.WriteLine(typeof(Foo).Name);
}
}
As was mentioned in the comments, that means that when you use nameof
on type parameters in a generic type, don't expect to get the name of the actual dynamic type used as a type parameter instead of just the type parameter's name. So this:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine(nameof(T));
}
}
Will become this:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine("T");
}
}
Implicit and explicit typing with C# 6 nameof
The language team felt that this wasn't worth the spec complexity.
You can see the discussion here.
The underlying reason for this behavior is that the spec says (§8.5.1) names declared with var
aren't visible in the declaring statement, since before nameof
, there was no way in which that could be valid.
Implicitly typed local variable declarations are subject to the following restrictions:
- ...
- The initializer expression cannot refer to the declared variable itself
Without var
, statements like int x = x = 1;
or int x = 1, y = x;
are legal; with var
, nothing in that form is valid.
Related Topics
Badimageformatexception When Loading 32 Bit Dll, Target Is X86
Ef Code First - How to Set Identity Seed
How to Copy a File While It Is Being Used by Another Process
How to Use Shell32 Within a C# Application
How to Display Items in Canvas Through Binding
Nested "From" Linq Query Expressed with Extension Methods
Entity Framework 6 Code First Custom Functions
Loop Through All Controls of a Form, Even Those in Groupboxes
What Is the Use of 'Abstract Override' in C#
Initial Capacity of Collection Types, E.G. Dictionary, List
Difference Between Delegate.Invoke and Delegate()
Store a Reference to a Value Type
How to Automatically Display All Properties of a Class and Their Values in a String
C# How to Loop While Mouse Button Is Held Down
How to "Zip" or "Rotate" a Variable Number of Lists