Оценивается ли nameof() во время компиляции?

В C# 6 вы можете использовать nameof() Оператор, чтобы получить строку, содержащую имя переменной или типа.

Это оценивается во время компиляции или во время выполнения с помощью некоторого API Roslyn?

2 ответа

Решение

Да. nameof() оценивается во время компиляции. Глядя на последнюю версию спецификации:

Имя выражения является константой. Во всех случаях nameof(...) вычисляется во время компиляции для создания строки. Его аргумент не оценивается во время выполнения и считается недоступным кодом (однако он не выдает предупреждение "недоступный код").

От имени оператора - v5

Вы можете увидеть это на примере 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 так же эффективно, как объявление строковой переменной.

Другие вопросы по тегам