web-dev-qa-db-fra.com

Le nom de () est-il évalué au moment de la compilation?

En C # 6, vous pouvez utiliser l'opérateur nameof() pour obtenir une chaîne contenant le nom d'une variable ou d'un type.

Est-ce évalué au moment de la compilation ou à l'exécution via une API Roslyn?

111
Gigi

Oui. nameof() est évalué au moment de la compilation. En regardant la dernière version des spécifications:

Le nom de l'expression est une constante. Dans tous les cas, nameof (...) est évalué au moment de la compilation pour produire une chaîne. Son argument n'est pas évalué au moment de l'exécution et est considéré comme du code inaccessible (cependant, il n'émet pas d'avertissement "code inaccessible").

De nom de l'opérateur - v5

Vous pouvez le voir avec cet exemple TryRoslyn où ceci:

public class Foo
{
    public void Bar()
    {
        Console.WriteLine(nameof(Foo));
    }
}

Est compilé et décompilé en ceci:

public class Foo
{
    public void Bar()
    {
        Console.WriteLine("Foo");
    }
}

Son équivalent d'exécution est:

public class Foo
{
    public void Bar()
    {
        Console.WriteLine(typeof(Foo).Name);
    }
}

Comme cela a été mentionné dans les commentaires, cela signifie que lorsque vous utilisez nameof sur des paramètres de type dans un type générique, ne vous attendez pas à obtenir le nom du type dynamique réel utilisé comme paramètre de type au lieu de simplement le type nom du paramètre. Donc ça:

public class Foo
{
    public void Bar<T>()
    {
        Console.WriteLine(nameof(T));
    }
}

Deviendra ceci:

public class Foo
{
    public void Bar<T>()
    {
        Console.WriteLine("T");
    }
}
116
i3arnon

Je voulais enrichir la réponse fournie par @ I3arnon avec une preuve qu'il est évalué au moment de la compilation.

Supposons que je souhaite imprimer le nom d'une variable dans la console à l'aide de l'opérateur nameof:

 var firstname = "Gigi";
 var varname = nameof(firstname);
 Console.WriteLine(varname); // Prints "firstname" to the console

Lorsque vous extrayez le MSIL généré, vous verrez qu'il est équivalent à une déclaration de chaîne car une référence d'objet à une chaîne est poussée vers la pile à l'aide de l'opérateur 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)

Vous remarquerez que la déclaration de la chaîne de prénom et l'utilisation de l'opérateur nameof génèrent le même code dans MSIL, ce qui signifie que nameof est aussi efficace que la déclaration d'une variable de chaîne.

58
Faris Zacina