2014-10-20 5 views
10

Se ho un codice come questo:Perché non è possibile ottenere nomi di variabili locali usando Reflection?

public class Program 
{ 
    public static void Main() 
    { 
     string bar = ""; 
     int foo = 24; 
    } 
} 

posso ottenere le variabili locali dichiarate in Main utilizzando:

var flag = BindingFlags.Static | BindingFlags.Public; 
var fields = typeof(Program).GetMethod("Main", flags).GetMethodBody().LocalVariables; 

Questo restituisce un IList<LocalVariableInfo> e LocalVariableInfo ha solo tre proprietà: IsPinned, LocalIndex e LocalType. Quindi non esiste una proprietà Name.

Quello che mi chiedo è che si possono vedere i nomi delle variabili nel generato IL code:

.method public hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  11 (0xb) 
    .maxstack 1 
    .locals init ([0] string bar, 
      [1] int32 foo) 
    IL_0000: nop 
    IL_0001: ldstr  "" 
    IL_0006: stloc.0 
    IL_0007: ldc.i4.s 24 
    IL_0009: stloc.1 
    IL_000a: ret 
} // end of method Program::Main 

ma non è possibile ottenere utilizzando Reflection .IS perché le variabili locali non hanno un nome e sono accessibili solo dai loro indici (se sì, come lo ILDASM.exe mostra i nomi?), o perché tale funzione non è implementata? O se è possibile utilizzare un altro modo, la domanda sarebbe, come?

Nota: ho visto alcune domande come this e la maggior parte di esse utilizza Expressions per ottenere il nome della variabile. Non funziona se mi piacerebbe avere tutti i locali comprese le variabili temporanee generate dal compilatore.

+1

I nomi sono presenti dopo aver rimosso i file PDB? – dasblinkenlight

+1

@dasblinkenlight sono, ma vedo nomi temporanei come V_0 e V_1 invece di nomi attuali –

risposta

6

Bisogna distinguere tra la forma testuale leggibile del CLI e la forma compilato leggibile dalla macchina di CLI.

Nel testo CLI, le variabili locali possono infatti avere nomi (vedere §II.15.4.1.3 dell'ECMA-335, come spiegato nella risposta di Damien).

Ma nel formato binario, le variabili locali non hanno nomi. Per questo, guarda §II.23.2.6, dove è specificato il formato binario per la firma di una variabile locale di un metodo (elenco di tutte le sue variabili locali).E non contiene alcuna menzione di nomi di variabili:

LocalVarSig

Quindi, se qualche strumento vuole sapere il nome originale di una variabile locale, deve esaminare le informazioni di debug contenute nel file PDB . Se questo non è presente, non c'è modo di scoprire il nome.

+0

Continuavo a cercare informazioni su come fosse effettivamente codificato, ma non riuscivo a trovarlo. –

4

Da MSDN:

nomi delle variabili locali non vengono mantenute nei metadati. In Microsoft intermediate language (MSIL), le variabili locali sono accessibili dalla loro posizione nella firma della variabile locale.

2

Penso che questo sia dovuto al fatto che il nome della variabile visualizzato in ILDasm proviene dal file pdb, non dall'assembly stesso. Se vuoi ottenerli, dovrai leggere anche il pdb.

6

Penso che stai guardando una build di debug. La parte della dichiarazione .locals è facoltativa - quindi non è possibile garantire che i nomi vengano mantenuti.

Vedi MS Partition II che descrive l'IL metadati, sezione 15.4.1.3 per ulteriori dettagli:

MethodBodyItem ::= … 
    .locals [ init ] ‘(’ LocalsSignature ‘)’ 
LocalsSignature ::= Local [ ‘,’ Local ]* 
Local ::= Type [ Id ] 
+1

@PatrickHofman - grazie. Il mio problema è che, naturalmente, mi riferisco sempre a una copia locale di questi file, ma poi mi sforzo di fornire un collegamento. –

Problemi correlati