C# 6.0C# 6.0 has a lot of new features, one of them is nameof operator. Let's see how it's implemented internally and what we can do with it.

This operator will help us get rid of "magic strings" in our code. We all know following use case:

public void Method(int arg)
{
    if (arg < 0)
    {
        throw new ArgumentOutOfRangeException("arg");
    }
}

With nameof operator we can rewrite code in a nicer way:

public void Method(int arg)
{
    if (arg < 0)
    {
        throw new ArgumentOutOfRangeException(nameof(arg));
    }
}

That is! nameof just returns a string representation of variable\method\type\propery\field. This might be very helpful during refactoring, you do not need to worry about string literals in your code anymore :)

The same as String Interpolation and Null Propagation operator, nameof is just a syntax sugar. During compilation process, whole expression will be replaced by a string. Let's see following example:

static void Main(string[] args)
{
    Console.WriteLine(nameof(args));
    // Console output: args
}

And IL code:

IL_0001:  ldstr      "args"
IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)

As we can see in line IL_0001, "args" is pushed on the stack with a ldsrt instruction.

Because it is a "compile-time operator" we cannot use expressions in the nameof operator. Following code will not compile because args.ToString() can be evaluated only in run-time:

Console.WriteLine(nameof(args.ToString().Length));

Here are more examples of nameof use:

namespace MyNameSpace
{
    internal enum ETestEnum
    {
        FirstValue
    }

    internal class Program
    {
        private static string privateField;
        public static string PublicProperty { get; set; }

        static void Main(string[] args)
        {
            var localVar = 1;

            // local variable
            Console.WriteLine(nameof(localVar));
            // field
            Console.WriteLine(nameof(privateField));
            // property
            Console.WriteLine(nameof(PublicProperty));
            // argument
            Console.WriteLine(nameof(args));
            // method
            Console.WriteLine(nameof(Main));
            // program
            Console.WriteLine(nameof(Program));
            // namespace
            Console.WriteLine(nameof(MyNameSpace));

            // generic type
            Console.WriteLine(nameof(Action<Program, Program>));
            //generic type's member
            Console.WriteLine(nameof(Action<Program, Program>.Method));
            // generic method
            Console.WriteLine(nameof(GenericMethod));
            
            // enum
            Console.WriteLine(nameof(ETestEnum));
            // enum's value
            Console.WriteLine(nameof(ETestEnum.FirstValue));
        }

        private static void GenericMethod<T>()
        {
        }
    }
}

Let's take a closer look at generic classes and methods. In case of Action<Program, Program> we will see only Action. The same with generic methods.

Also, if you want to get enum's value name you should use nameof operator instead of .ToString() method.

// preferable way
Console.WriteLine(nameof(ETestEnum.FirstValue));

// "old school" way
Console.WriteLine(ETestEnum.FirstValue.ToString());

If we look at IL code we will see why nameof is preferable in this case:

IL_004e:  ldstr      "FirstValue"
IL_0053:  call       void [mscorlib]System.Console::WriteLine(string)
IL_0058:  nop
IL_0059:  ldc.i4.0
IL_005a:  stloc.0
IL_005b:  ldloca.s   V_0
IL_005d:  constrained. MyNameSpace.ETestEnum
IL_0063:  callvirt   instance string [mscorlib]System.Object::ToString()
IL_0068:  call       void [mscorlib]System.Console::WriteLine(string)

As you can see, string constant (IL_004e) will be much more efficient than callvirt instruction (IL_0063).

Everyday use cases

INotifyPropertyChanged

public int Property
{
    get { return this.p; }
    set
    {
        this.p = value;
        PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.p));
    }
}

Parameters Validation

void Method(string arg)
{
    if (arg == null)
    {
        throw new ArgumentNullException(nameof(arg));
    }
}

XAML Dependency Property

public static DependencyProperty AddressProperty =
    DependencyProperty.Register(
        nameof(Address), 
        typeof(AddressType), 
        typeof(MainWindow));

Logging

void Method(int arg)
{
    Log(nameof(Method), "Method Logged");
}

And much, much more...