Оценивается ли nameof() во время компиляции?
В C# 6 вы можете использовать nameof()
Оператор, чтобы получить строку, содержащую имя переменной или типа.
Это оценивается во время компиляции или во время выполнения с помощью некоторого API Roslyn?
2 ответа
Да. nameof()
оценивается во время компиляции. Глядя на последнюю версию спецификации:
Имя выражения является константой. Во всех случаях nameof(...) вычисляется во время компиляции для создания строки. Его аргумент не оценивается во время выполнения и считается недоступным кодом (однако он не выдает предупреждение "недоступный код").
Вы можете увидеть это на примере 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);
}
}
Как уже упоминалось в комментариях, это означает, что когда вы используете nameof
для параметров типа в универсальном типе не ожидайте получить имя фактического динамического типа, используемого в качестве параметра типа, а не только имя параметра типа. Итак, это:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine(nameof(T));
}
}
Станет так:
public class Foo
{
public void Bar<T>()
{
Console.WriteLine("T");
}
}
Я хотел дополнить ответ, предоставленный @I3arnon, доказательством того, что он оценивается во время компиляции.
Давайте предположим, что я хочу напечатать имя переменной в консоли, используя nameof
оператор:
var firstname = "Gigi";
var varname = nameof(firstname);
Console.WriteLine(varname); // Prints "firstname" to the console
При просмотре сгенерированного 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)
Вы заметите, что объявление строки имени и использование nameof
Оператор генерирует тот же код в MSIL, что означает nameof
так же эффективно, как объявление строковой переменной.