i3a*_*non 117
是.nameof()在编译时进行评估.查看最新版本的规格:
表达式的名称是常量.在所有情况下,在编译时评估 nameof(...)以生成字符串.它的参数不在运行时进行评估,并且被认为是无法访问的代码(但它不会发出"无法访问的代码"警告).
您可以通过此TryRoslyn示例看到:
public class Foo
{
public void Bar()
{
Console.WriteLine(nameof(Foo));
}
}
Run Code Online (Sandbox Code Playgroud)
编译并反编译成:
public class Foo
{
public void Bar()
{
Console.WriteLine("Foo");
}
}
Run Code Online (Sandbox Code Playgroud)
它的运行时间相当于:
public class Foo
{
public void Bar()
{
Console.WriteLine(typeof(Foo).Name);
}
}
Run Code Online (Sandbox Code Playgroud)
正如在注释中提到的那样,这意味着当您nameof在泛型类型中使用类型参数时,不要期望获得用作类型参数的实际动态类型的名称,而不仅仅是类型参数的名称.所以这:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine(nameof(T));
}
}
Run Code Online (Sandbox Code Playgroud)
会变成这样的:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine("T");
}
}
Run Code Online (Sandbox Code Playgroud)
Far*_*ina 57
我希望丰富@ I3arnon提供的答案,并证明它是在编译时进行评估的.
假设我想使用nameof运算符在Console中打印变量的名称:
var firstname = "Gigi";
var varname = nameof(firstname);
Console.WriteLine(varname); // Prints "firstname" to the console
Run Code Online (Sandbox Code Playgroud)
当您检查生成的MSIL时,您将看到它等同于字符串声明,因为对字符串的对象引用使用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)
Run Code Online (Sandbox Code Playgroud)
您会注意到声明firstname字符串并使用nameof运算符在MSIL中生成相同的代码,这意味着nameof与声明字符串变量一样高效.