Is nameof() evaluated at compile-time?

后端 未结 2 1659
悲哀的现实
悲哀的现实 2020-11-28 10:39

In C# 6, you can use the nameof() operator to get a string containing the name of a variable or a type.

Is this evaluated at compile-time, or at runtime via some Ros

相关标签:
2条回答
  • 2020-11-28 11:31

    I wanted to enrich the answer provided by @I3arnon with a proof that it is evaluated at compile-time.

    Let's assume i want to print the name of a variable in the Console using the nameof operator:

     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)
    

    You will notice that declaring the firstname string and using the nameof operator generates the same code in MSIL, which means nameof is as efficient as declaring a string variable.

    0 讨论(0)
  • 2020-11-28 11:33

    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");
        }
    }
    
    0 讨论(0)
提交回复
热议问题