property - nameof c#
¿Se evalúa nameof() en tiempo de compilación? (2)
Quería enriquecer la respuesta proporcionada por @ I3arnon con una prueba de que se evalúa en tiempo de compilación.
Supongamos que quiero imprimir el nombre de una variable en la consola usando el operador
nameof
:
var firstname = "Gigi";
var varname = nameof(firstname);
Console.WriteLine(varname); // Prints "firstname" to the console
Cuando revise el MSIL generado, verá que es equivalente a una declaración de cadena porque una referencia de objeto a una cadena se inserta en la pila utilizando el operador
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)
Notará que declarar la cadena de nombre y usar el operador
nameof
genera el mismo código en MSIL, lo que significa que
nameof
es tan eficiente como declarar una variable de cadena.
En C # 6, puede usar el operador
nameof()
para obtener una cadena que contiene el nombre de una variable o un tipo.
¿Se evalúa esto en tiempo de compilación o en tiempo de ejecución a través de alguna API de Roslyn?
Si.
nameof()
se evalúa en tiempo de compilación.
Mirando la última versión de las especificaciones:
El nombre de la expresión es una constante. En todos los casos, el nombre de (...) se evalúa en tiempo de compilación para producir una cadena. Su argumento no se evalúa en tiempo de ejecución y se considera código inalcanzable (sin embargo, no emite una advertencia de "código inalcanzable").
Puede ver eso con este ejemplo de TryRoslyn donde esto:
public class Foo
{
public void Bar()
{
Console.WriteLine(nameof(Foo));
}
}
Se compila y descompila en esto:
public class Foo
{
public void Bar()
{
Console.WriteLine("Foo");
}
}
Su equivalente en tiempo de ejecución es:
public class Foo
{
public void Bar()
{
Console.WriteLine(typeof(Foo).Name);
}
}
Como se mencionó en los comentarios, eso significa que cuando usa los parámetros
nameof
en type en un tipo genérico, no espere obtener el nombre del tipo dinámico real utilizado como parámetro de tipo en lugar de solo el nombre del parámetro de tipo.
Así que esto:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine(nameof(T));
}
}
Se convertirá en esto:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine("T");
}
}