W C # 6 możesz użyć nameof()
operatora, aby uzyskać ciąg zawierający nazwę zmiennej lub typu.
Czy jest to oceniane w czasie kompilacji, czy w czasie wykonywania za pośrednictwem interfejsu API Roslyn?
W C # 6 możesz użyć nameof()
operatora, aby uzyskać ciąg zawierający nazwę zmiennej lub typu.
Czy jest to oceniane w czasie kompilacji, czy w czasie wykonywania za pośrednictwem interfejsu API Roslyn?
Odpowiedzi:
Tak. nameof()
jest oceniany w czasie kompilacji. Patrząc na najnowszą wersję specyfikacji:
Nazwa wyrażenia jest stałą. We wszystkich przypadkach nameof (...) jest oceniane w czasie kompilacji w celu utworzenia ciągu. Jego argument nie jest oceniany w czasie wykonywania i jest uważany za nieosiągalny kod (jednak nie emituje ostrzeżenia „nieosiągalny kod”).
Możesz to zobaczyć w tym przykładzie TryRoslyn, gdzie:
public class Foo
{
public void Bar()
{
Console.WriteLine(nameof(Foo));
}
}
Jest kompilowany i dekompilowany do tego:
public class Foo
{
public void Bar()
{
Console.WriteLine("Foo");
}
}
Jego odpowiednik w czasie wykonywania to:
public class Foo
{
public void Bar()
{
Console.WriteLine(typeof(Foo).Name);
}
}
Jak wspomniano w komentarzach, oznacza to, że gdy używasz nameof
parametrów typu w typie ogólnym, nie spodziewaj się, że otrzymasz nazwę rzeczywistego typu dynamicznego używanego jako parametr typu, zamiast tylko nazwy parametru typu. Więc to:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine(nameof(T));
}
}
Stanie się tym:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine("T");
}
}
Chciałem wzbogacić odpowiedź udzieloną przez @ I3arnon o dowód, że jest oceniana w czasie kompilacji.
Załóżmy, że chcę wydrukować nazwę zmiennej w konsoli za pomocą nameof
operatora:
var firstname = "Gigi";
var varname = nameof(firstname);
Console.WriteLine(varname); // Prints "firstname" to the console
Kiedy sprawdzisz wygenerowany MSIL, zobaczysz, że jest on równoważny deklaracji ciągu, ponieważ odwołanie do obiektu do ciągu jest wypychane na stos za pomocą ldstr
operatora:
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)
Zauważysz, że zadeklarowanie ciągu firstname i użycie nameof
operatora generuje ten sam kod w MSIL, co oznacza, że nameof
jest tak samo wydajne, jak deklarowanie zmiennej łańcuchowej.
nameof
operator, a nie zwykły ciąg znaków zakodowanych na stałe?