2010-03-24 10 views
96

Se hai mai usato Reflector, probabilmente hai notato che il compilatore C# genera tipi, metodi, campi e variabili locali che meritano la visualizzazione "speciale" dal debugger. Ad esempio, le variabili locali che iniziano con 'CS $' non vengono visualizzate all'utente. Esistono altre convenzioni di denominazione speciali per tipi di chiusura di metodi anonimi, campi di supporto di proprietà automatiche e così via.Dove scoprire i "nomi magici" del debugger VS

La mia domanda: dove conoscere queste convenzioni di denominazione? Qualcuno sa di qualche documentazione?

Il mio obiettivo è far sì che PostSharp 2.0 utilizzi le stesse convenzioni.

risposta

190

Questi sono dettagli di implementazione non documentati del compilatore e soggetti a modifiche in qualsiasi momento. (UPDATE: Vedere GeneratedNames.cs nelle fonti C# per i dettagli correnti; la descrizione che segue è un po 'out-of-date.)

Tuttavia, dato che sono un bravo ragazzo, qui sono alcuni di quei dettagli:

Se si dispone di una variabile locale inutilizzata che l'ottimizzatore rimuove, si inviano comunque informazioni di debug sul PDB. Abbiamo bloccato il suffisso __Deleted$ su tali variabili in modo che il debugger sappia che erano nel codice sorgente ma non rappresentato nel binario.

Gli slot di variabile temporanea assegnati dal compilatore hanno nomi con il modello CS $ X $ Y, dove X è il "tipo temporaneo" e Y è il numero di temporaries assegnati finora. I tipi temporanee sono:

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. 

tipi temporanee tra 8 e 264 sono ulteriori depositi Indice array di array multidimensionali.

I tipi temporanei sopra 264 vengono utilizzati per i provvisori che coinvolgono l'istruzione fissa che fissa una stringa.

nomi speciali generati dal compilatore vengono generati per:

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

Il modello per la generazione di nomi magici è: P<N>C__SI dove:

  • P è CS $ per i delegati nella cache e istanze di classi di visualizzazione, vuoto altrimenti.
  • N è il nome originale associato con la cosa, se qualsiasi
  • C è il carattere 1 attraverso s sopra elencati
  • S è un suffisso descrittivo ("stato" "corrente", e così via) in modo che non è necessario avere la tabella sopra memorizzata durante la lettura dei metadati.
  • I è un numero univoco opzionale
+2

Grazie! Vedrò se riesco a far sì che le classi di chiusura di PostSharp si comportino bene come ciò che genera il compilatore C#! –

+3

Cos'è un provvisorio duraturo? – SLaks

+7

@SLaks: l'opposto di un temporaneo di breve durata. I provvisori durevoli sono essenzialmente variabili locali senza nomi; hanno una posizione specifica nello stack che vive per tutta la vita del frame dello stack. I provvisori di breve durata vengono semplicemente messi in pila quando è necessario il loro spazio di archiviazione e poi scaricati quando non è più necessario. I provvisori durevoli sono molto più facili da eseguire il debug, ma possono rendere le durate dei provvisori molto più lunghe. Generiamo provvisori durevoli quando le ottimizzazioni sono disattivate. –

Problemi correlati