Is nameof() evaluated at compile-time?

匿名 (未验证) 提交于 2019-12-03 02:52:02

问题:

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 Roslyn API?

You can read about the nameof() operator at the official discussion pointed out in the accepted answer, or the dedicated post at my blog. On 2000things.com, you can find its description and example of its use.

回答1:

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()     {         Console.WriteLine(nameof(T));     } } 

Will become this:

public class Foo {     public void Bar()     {         Console.WriteLine("T");     } } 


回答2:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!