nameof()是在编译时计算的吗?

在C#6中,可以使用nameof()运算符来获取包含variables或types名称的string。

这是评估在编译时,或在运行时通过一些Roslyn API?

您可以在接受的答案中指出的官方讨论或我博客上的专门post中阅读有关nameof()运算符的信息 。 在2000things.com上 ,你可以find它的描述和使用的例子。

是。 nameof()在编译时被评估。 看最新版本的规格:

expression式的名字是一个常量。 在所有情况下,nameof(…) 在编译时计算出来以产生一个string。 它的参数在运行时不被评估,被认为是无法访问的代码(但不会发出“无法访问的代码”警告)。

从运营商的名字 – v5

你可以看到这个TryRoslyn例子 :

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

被编译和反编译到这里:

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

其运行时间相当于:

 public class Foo { public void Bar() { Console.WriteLine(typeof(Foo).Name); } } 

正如在注释中提到的那样,这意味着当您在genericstypes的types参数上使用nameof时,不要期望获取用作types参数的实际dynamictypes的名称,而不仅仅是types参数的名称。 所以这:

 public class Foo { public void Bar<T>() { Console.WriteLine(nameof(T)); } } 

会成为这样的:

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

我想丰富@ I3arnon提供的答案 ,certificate它在编译时被评估。

让我们假设我想要使用nameof运算符在控制台中打印variables的名称:

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

当你签出生成的MSIL时,你会发现它相当于一个string声明,因为一个string的对象引用被使用ldstr操作符推送到堆栈:

 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) 

您会注意到声明名字string并使用nameof运算符会在MSIL中生成相同的代码,这意味着nameof与声明stringvariables的效率相同。