Roslyn est la nouvelle plateforme de compilation. Il n'est utilisé qu'au moment de la compilation.
Paulo Morgado
2
@PauloMorgado ce n'est pas vrai, vous pouvez utiliser Rosyln au moment de l'exécution pour faire des choses. Comme la construction d'un éditeur de code en direct ou l'utilisation de l'analyse syntaxique de Rosyln pour faire des choses avec des arbres ou des expressions ou quelque chose du
genre
@ChrisMarisic c'est mon impression, mais je n'ai pas répondu car mes connaissances sur le sujet sont limitées (d'où ma question). Je suis tombé sur ceci: scriptcs.net qui est un très bon exemple de la puissance de Roslyn, et qui, je crois, fait des choses d'exécution, mais je peux me tromper car je ne suis pas très bien informé à ce sujet.
Gigi
@ChrisMarisic, donc, ce que vous dites, c'est que vous pouvez utiliser Roslyn pour créer du code en direct à partir de la source, et non du seul binaire en cours d'exécution. Et vous utilisez toujours Roslyn pour transformer la source en binaires qui n'utiliseront pas Roslyn pour changer ces binaires. Si vous ne pouvez absolument pas utiliser Roslyn au moment de l'exécution, vous ne pourrez jamais compiler de code.
Paulo Morgado
Réponses:
119
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é à l'exécution, et est considéré comme du code inaccessible (cependant il n'émet pas d'avertissement "code inaccessible").
Comme mentionné dans les commentaires, cela signifie que lorsque vous utilisez des nameofparamè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 du nom du paramètre de type uniquement. Donc ça:
Supposons que je souhaite imprimer le nom d'une variable dans la console à l'aide de l' nameofopérateur:
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' ldstropérateur:
Vous remarquerez que déclarer la chaîne de prénom et utiliser l' nameofopérateur génère le même code dans MSIL, ce qui signifie qu'il nameofest aussi efficace que de déclarer une variable de chaîne.
Si le MSIL est décompilé en code source, dans quelle mesure sera-t-il facile pour le décompilateur de reconnaître qu'il s'agissait d'un nameofopérateur et non d'une chaîne codée en dur?
ADTC
11
C'est une bonne question! vous pouvez le poster comme une nouvelle question sur SO si vous voulez obtenir une explication détaillée :) .. cependant la réponse courte est que le décompilateur ne pourra pas comprendre que c'était un opérateur nameof, mais utilisera une chaîne littérale à la place . J'ai vérifié que c'était le cas avec ILSpy et Reflector.
Faris Zacina
2
@ADTC: Comme le nom de est entièrement remplacé par load-a-string-on-the-stack, comment le décompilateur pourrait-il même essayer de deviner que c'était un nom de, et pas un simple paramètre constant?
quetzalcoatl
2
C'est intéressant. Peut-être que le décompilateur pourrait vérifier la chaîne par rapport au contexte actuel (nom de la méthode / propriété / etc dans laquelle vous vous trouvez). Pourtant, il n'y a aucun moyen pour qu'il soit fiable à 100% - vous avez peut-être utilisé une chaîne codée en dur après tout.
Gigi
2
Bien que je convienne que vous ne pouvez pas savoir si c'est un nom après la compilation, je ne vois aucune indication que ILSpy ou Reflector prennent en charge C # 6 pour le moment. Si tel est le cas, vous ne pouvez pas le tester @TheMinister
Réponses:
Oui.
nameof()
est évalué au moment de la compilation. En regardant la dernière version des spécifications:Depuis le nom de l'opérateur - v5
Vous pouvez le voir avec cet exemple TryRoslyn où ceci:
Est compilé et décompilé en ceci:
Son équivalent d'exécution est:
Comme mentionné dans les commentaires, cela signifie que lorsque vous utilisez des
nameof
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 du nom du paramètre de type uniquement. Donc ça:Deviendra ceci:
la source
Je voulais enrichir la réponse fournie par @ I3arnon avec une preuve qu'elle est évaluée à la compilation.
Supposons que je souhaite imprimer le nom d'une variable dans la console à l'aide de l'
nameof
opérateur: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'
ldstr
opérateur:Vous remarquerez que déclarer la chaîne de prénom et utiliser l'
nameof
opérateur génère le même code dans MSIL, ce qui signifie qu'ilnameof
est aussi efficace que de déclarer une variable de chaîne.la source
nameof
opérateur et non d'une chaîne codée en dur?