В C # 6 вы можете использовать nameof()
оператор для получения строки, содержащей имя переменной или типа.
Это оценивается во время компиляции или во время выполнения через какой-нибудь Roslyn API?
В C # 6 вы можете использовать nameof()
оператор для получения строки, содержащей имя переменной или типа.
Это оценивается во время компиляции или во время выполнения через какой-нибудь Roslyn API?
Ответы:
Да. nameof()
оценивается во время компиляции. Глядя на последнюю версию спецификаций:
Выражение 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
он так же эффективен, как объявление строковой переменной.
nameof
оператор, а не простая жестко закодированная строка?