Où en savoir plus sur les `` noms magiques '' du débogueur VS

110

Si vous avez déjà utilisé Reflector, vous avez probablement remarqué que le compilateur C # génère des types, des méthodes, des champs et des variables locales, qui méritent un affichage «spécial» par le débogueur. Par exemple, les variables locales commençant par «CS $» ne sont pas affichées pour l'utilisateur. Il existe d'autres conventions de dénomination spéciales pour les types de fermeture des méthodes anonymes, les champs de sauvegarde des propriétés automatiques, etc.

Ma question: où en savoir plus sur ces conventions de dénomination? Quelqu'un est-il au courant de certains documents?

Mon objectif est de faire en sorte que PostSharp 2.0 utilise les mêmes conventions.

Gaël Fraiteur
la source

Réponses:

209

Il s'agit de détails d'implémentation non documentés du compilateur et susceptibles d'être modifiés à tout moment. (MISE À JOUR: voir GeneratedNames.cs dans les sources C # pour les détails actuels; la description ci-dessous est quelque peu obsolète.)

Cependant, comme je suis un gars sympa, voici quelques-uns de ces détails:

Si vous avez une variable locale inutilisée que l'optimiseur supprime, nous émettons quand même des informations de débogage pour elle dans la PDB. Nous avons collé le suffixe __Deleted$sur de telles variables afin que le débogueur sache qu'elles étaient dans le code source mais pas représentées dans le binaire.

Les emplacements de variables temporaires alloués par le compilateur reçoivent des noms avec le modèle CS $ X $ Y, où X est le «genre temporaire» et Y est le nombre de temporaires alloués jusqu'à présent. Les types temporaires sont:

0 --> short lived temporaries
1 --> return value temporaries
2 --> temporaries generated for lock statements
3 --> temporaries generated for using statements
4 --> durable temporaries
5 --> the result of get enumerator in a foreach
6 --> the array storage in a foreach
7 --> the array index storage in a foreach.  

Les types temporaires entre 8 et 264 sont des stockages d'index de tableau supplémentaires pour les tableaux multidimensionnels.

Les types temporaires au-dessus de 264 sont utilisés pour les temporaires impliquant l'instruction fixed fixant une chaîne.

Des noms spéciaux générés par le compilateur sont générés pour:

1 --> the iterator state ("state")
2 --> the value of current in an iterator ("current")
3 --> a saved parameter in an iterator
4 --> a hoisted 'this' in an iterator ("this")
5 --> a hoisted local in an iterator
6 --> the hoisted locals from an outer scope
7 --> a hoisted wrapped value ("wrap")
8 --> the closure class instance ("locals")
9 --> the cached delegate instance ("CachedAnonymousMethodDelegate")
a --> the iterator instance ("iterator")
b --> an anonymous method
c --> anonymous method closure class ("DisplayClass")
d --> iterator class
e --> fixed buffer struct ("FixedBuffer")
f --> anonymous type ("AnonymousType")
g --> initializer local ("initLocal")
h --> query expression temporary ("TransparentIdentifier")
i --> anonymous type field ("Field")
j --> anonymous type type parameter ("TPar")
k --> auto prop field ("BackingField")
l --> iterator thread id
m --> iterator finally ("Finally")
n --> fabricated method ("FabricatedMethod")
o --> dynamic container class ("SiteContainer")
p --> dynamic call site ("Site")
q --> dynamic delegate ("SiteDelegate")
r --> com ref call local ("ComRefCallLocal")
s --> lock taken local ("LockTaken")

Le modèle pour générer des noms magiques est: P<N>C__SIoù:

  • P est CS $ pour les délégués mis en cache et les instances de classe d'affichage, vide dans le cas contraire.
  • N est le nom d'origine associé à l'objet, le cas échéant
  • C est le caractère 1 à s indiqué ci-dessus
  • S est un suffixe descriptif ("courant", "état", etc.) pour que vous n'ayez pas à mémoriser le tableau ci-dessus lors de la lecture des métadonnées.
  • I est un numéro unique facultatif
Eric Lippert
la source
2
Je vous remercie! Je vais voir si je peux faire en sorte que les classes de fermeture PostSharp se comportent aussi bien que ce que le compilateur C # génère!
Gael Fraiteur
7
@SLaks: l'opposé d'un temporaire de courte durée. Les temporaires durables sont essentiellement des variables locales sans nom; ils ont un emplacement spécifique sur la pile qui dure toute la durée de vie du cadre de pile. Les temporaires de courte durée sont simplement poussés sur la pile lorsque leur stockage est nécessaire, puis supprimés lorsqu'il n'est plus nécessaire. Les temporaires durables sont beaucoup plus faciles à déboguer, mais peuvent allonger la durée de vie des temporaires. Nous générons des temporaires durables lorsque les optimisations sont désactivées.
Eric Lippert
J'ai un concept similaire aux classes de fermeture, mais au lieu d'avoir des paramètres hissés comme champs, je les ai comme variables locales. Cela fonctionne plutôt bien pour les paramètres, mais comment dire au débogueur que «this» n'est pas «ldarg.0» mais la variable locale d'index 4? Y a-t-il un nom magique?
Gael Fraiteur
23
@Eric - pourriez-vous mettre à jour cette réponse avec des noms générés par C # 5.0 (async / await)? J'ai vu de nouveaux préfixes :)
Gael Fraiteur