Difference between nameof and typeof
Asked Answered
U

7

41

Correct me if I am wrong, but doing something like

var typeOfName = typeof(Foo).Name;

and

var nameOfName = nameof(Foo);

should give you exactly the same output. One of the understandable reasons according to this source: https://msdn.microsoft.com/en-us/library/dn986596.aspx is that

"Using nameof helps keep your code valid when renaming definitions"

If you want to get the class instance as string it is not possible to do something like that:

var fooInstance = new Foo();
var nameOfName = nameof(fooInstance);

however, you can do something like:

static string GetName<T>(T item) where T : class 
{
  return typeof(T).GetProperties()[0].Name;
}
var typeOfName2 = GetName(new { fooInstance });

In both cases (typeof and nameof) a refactoring is possible, so I dont see any other reason for reinventing another higher level keyword, such as nameof, to perform something that already exists. Are there any differences between them that I don't clearly see?

Finally, I would appreciate if could someone point me to a reference source to have a look at the implementation of nameof. Does it use Reflection?

Update 1: Taken from here

nameof is apparently as efficient as declaring a string variable. No reflection or whatsoever!

var firstname = "Gigi";
 var varname = nameof(firstname);
 Console.WriteLine(varname); // Prints "firstname" to the console

When you check out the MSIL generated you will see that it is equivalent to a string declaration because an object reference to a string gets pushed to the stack using the ldstr operator:

IL_0001: ldstr "Gigi"
IL_0006: stloc.0
IL_0007: ldstr "firstname"
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: call void [mscorlib]System.Console::WriteLine(string)
Unblessed answered 11/11, 2015 at 11:23 Comment(6)
nameof(fooInstance) returns "fooInstance". With nameof you get the name of the variable, not the name of the type.Hedgepeth
it gets the string version of it's variable. nameof(aaa) will return "aaa"Koester
static string GetName<T>(T item) does something completely different than typeof or nameof. It returns the name of a random property the Type has. It could also throw an exception if it's used in a different way than intended.Rubellite
I'd rather use nameof than add my own method with anonymous types.Fayola
nameof and typeof are not functionsBelew
I meant they are compile time features, hence you'll not see a "reference source implementation". Your examples are run time functions.Belew
A
41

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).

Alluvial answered 11/11, 2015 at 11:36 Comment(0)
P
21

Here's a benchmark test by using BenchmarkDotNet

// * Summary *

Host Process Environment Information:
BenchmarkDotNet.Core=v0.9.9.0
OS=Windows
Processor=?, ProcessorCount=8
Frequency=2740584 ticks, Resolution=364.8857 ns, Timer=TSC
CLR=CORE, Arch=64-bit ? [RyuJIT]
GC=Concurrent Workstation
dotnet cli version: 1.0.0-preview2-003133

Type=GetNameBenchmark  Mode=Throughput  LaunchCount=2
WarmupCount=10  TargetCount=200

     Method |     Median |    StdDev |
----------- |----------- |---------- |
     TypeOf | 16.0348 ns | 0.7896 ns |
     NameOf |  0.0005 ns | 0.0147 ns |
Pneumonoultramicroscopicsilicovolcanoconiosis answered 20/12, 2017 at 3:58 Comment(1)
Thanks for pointing out BenchmarkDotNet ... never heard of it beforeAlbemarle
S
12

Using Reflection to generate strings is possible, but is not very elegant and not always possible. You can't use Reflection in sandboxed code for example. And you can't use it on local variables. And it is expensive.

The nameof operator works at compile time. The compiler already knows the name when it parses the code. So can trivially generate the string literal. Very fast, can't possibly be faster, and no runtime restrictions.

Shalom answered 11/11, 2015 at 11:43 Comment(0)
S
6

There are several differences between them, but they are mainly practical reasons behind. Example 1:

It is more elegant to write something like

switch (e.ArgumentPropertyName)
{
    case nameof(aProperty):
    break;

    case "anotherProperty":
    break;
}

Try to refactor anotherProperty type and bang! the nameof will reflect the changes, the "anotherProperty" will pass silently and your code will never get executed within that case statement..

Example 2:

enum MetalEnum { Gold = 1,  Silver = 2, ... }

Which one is nicer?

Console.WriteLine(MetalEnum.Gold.ToString()); // finds the name at runtime (slower)

or

Console.WriteLine(nameof(MetalEnum.Gold)); // compile time (faster)

Example 3:

Finally, do you remember how ugly it is to write something like

PropertyChanged(this, new PropertyChangedEventArgs("Foo"));

Now you can write as beautifully as follows:

PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));
Sporting answered 11/11, 2015 at 13:50 Comment(0)
S
4

According to the documentation:

Used to obtain the simple (unqualified) string name of a variable, type, or member.

...

The argument to nameof must be a simple name, qualified name, member access, base access with a specified member, or this access with a specified member. The argument expression identifies a code definition, but it is never evaluated.

Because the argument needs to be an expression syntactically, there are many things disallowed that are not useful to list. The following are worth mentioning that produce errors: predefined types (for example, int or void), nullable types (Point?), array types (Customer[,]), pointer types (Buffer*), qualified alias (A::B), and unbound generic types (Dictionary<,>), preprocessing symbols (DEBUG), and labels (loop:).

The simple name that nameof obtains is the source name, not the metadata name.

So, this code:

using Integer = System.Int32;
var s = "a string";
Console.WriteLine(nameof(s));
Console.WriteLine(nameof(Integer));
Console.WriteLine(nameof(System.Int32));
void M<T>() { Console.WriteLine(nameof(T)); }
M<int>();
M<string>();

will print:

s
Integer
Int32
T
T
Sella answered 11/11, 2015 at 23:45 Comment(0)
D
3

Typeof returns Type objects. It is often used as a parameter or as a variable or field. The typeof operator is part of an expression that acquires the Type pointer.

class Program
{
    static Type _type = typeof(char); // Store Type as field.

    static void Main()
    {
    Console.WriteLine(_type); // Value type pointer
    Console.WriteLine(typeof(int)); // Value type
    Console.WriteLine(typeof(byte)); // Value type
    Console.WriteLine(typeof(Stream)); // Class type
    Console.WriteLine(typeof(TextWriter)); // Class type
    Console.WriteLine(typeof(Array)); // Class type
    Console.WriteLine(typeof(int[])); // Array reference type
    }
}

Output

System.Char
System.Int32
System.Byte
System.IO.Stream
System.IO.TextWriter
System.Array
System.Int32[]

Nameof, meanwhile, returns a string with a variable's name. It works at compile-time. It is a special compiler feature that simplifies some programs.

int size=100;
Console.WriteLine(nameof(size));

output:size

Dirichlet answered 11/11, 2015 at 11:37 Comment(0)
R
0

Typeof returns Type objects. It is often used as a parameter or as a variable or field. The typeof operator is part of an expression that acquires the Type pointer.

Nameof, meanwhile, returns a string with a variable's name. It works at compile-time. It is a special compiler feature that simplifies some programs.

Rutaceous answered 11/11, 2015 at 11:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.