2010-03-24 8 views
96

Si alguna vez ha usado Reflector, probablemente haya notado que el compilador C# genera tipos, métodos, campos y variables locales que merecen una visualización 'especial' por el depurador. Por ejemplo, las variables locales que comienzan con 'CS $' no se muestran al usuario. Existen otras convenciones de nomenclatura especiales para tipos de cierre de métodos anónimos, campos de respaldo de propiedades automáticas, etc.Dónde aprender sobre los 'nombres mágicos' del depurador VS

Mi pregunta: ¿dónde aprender sobre estas convenciones de nombres? ¿Alguien sabe sobre alguna documentación?

Mi objetivo es hacer que PostSharp 2.0 use las mismas convenciones.

Respuesta

190

Estos son detalles de implementación no documentados del compilador, y están sujetos a cambios en cualquier momento. (ACTUALIZACIÓN: Ver GeneratedNames.cs en las fuentes de C# para los detalles actuales; la descripción a continuación es un poco fuera de fecha.)

Sin embargo, ya que soy un buen tipo, aquí están algunos de esos detalles:

Si tiene una variable local no utilizada que el optimizador elimina, emitimos información de depuración de todos modos en el PDB. Pusimos el sufijo __Deleted$ en dichas variables para que el depurador sepa que estaban en el código fuente pero no representados en el binario.

Las ranuras variables temporales asignadas por el compilador reciben nombres con el patrón CS $ X $ Y, donde X es el "tipo temporal" e Y es el número de temporales asignados hasta el momento. Las clases son temporales:

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. 

clases temporales entre 8 y 264 son almacenamientos índice de matriz adicionales para matrices multidimensionales.

Los tipos temporales superiores a 264 se utilizan para los temporales que implican la instrucción fija que fija una cadena.

nombres especiales generados por el compilador se generan para:

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") 

El patrón para la generación de nombres mágicos es: P<N>C__SI donde:

  • P es CS $ para los delegados en caché y las instancias de clase pantalla, vacío de otra manera.
  • N es el nombre original asociada con la cosa, si cualquier
  • C es el carácter 1 a través de s enumerados anteriormente
  • S es un sufijo descriptivo ("estado" "actual", y así sucesivamente) para que no es necesario memorizar la tabla anterior al leer los metadatos.
  • I es un número único opcional
+2

¡Gracias! ¡Veré si puedo hacer que las clases de cierre de PostSharp se comporten tan bien como las que genera el compilador de C#! –

+3

¿Qué es un artículo temporal duradero? – SLaks

+7

@SLaks: lo contrario de un temporal efímero. Los temporales temporales son esencialmente variables locales sin nombres; tienen una ubicación específica en la pila que vive durante toda la vida del marco de pila. Los temporales temporales de corta vida simplemente se empujan en la pila cuando se necesita su almacenamiento y luego se apagan cuando ya no se necesitan. Los temporales temporales son mucho más fáciles de depurar, pero pueden alargar la vida útil de los temporales. Generamos temporales temporales cuando las optimizaciones están desactivadas. –

Cuestiones relacionadas