2009-04-04 9 views
9

C'è un modo in .NET, usando Reflection.Emit, per accedere all'elemento più in alto-uno dalla pila? Quindi se A è il più in alto e B il prossimo - Voglio elaborare B poi A. Sarebbe bello duplicare B sopra A (dato che posso semplicemente "inserire" il secondo B quando arrivo ad esso).Reflection.Emit - accede all'ultimo elemento ma-one dallo stack

Attualmente, sto dichiarando un locale:

LocalBuilder loc = il.DeclareLocal(typeof(Foo)); 
    il.Emit(OpCodes.Stloc, loc); // store and pop topmost stack item 
    // work with (pop) previous stack item 
    il.Emit(OpCodes.Ldloc, loc); // push old topmost stack item 

C'è un percorso che non ha bisogno locale esplicito?

risposta

7

Non credo. In IL non ci sono istruzioni come swap che ti permettano di fare ciò che vuoi. Perché vedi che usare un locale è discutibile? Se il compilatore JIT è abbastanza buono, ciò non comporterà un codice macchina più lento rispetto all'utilizzo di un'operazione di scambio ipotetico in IL.

+1

Per il "perché" - questo è nel codice generato che dovrebbe introdurre più gente del posto che voglio. Se potessi utilizzare la parte superiore dello stack, potrei risparmiare quantità non banali di spazio nello stack (i locali sono riservati indipendentemente dall'utilizzo, AFAIK). –

1

In linea con quanto KVB detto, si potrebbe provare una piccola funzione per fare un po riordino. Non sono sicuro se sarebbe più veloce.

+0

Buona idea, ma quasi certamente no; anche se la JUT l'ha sottolineato. –

1

Ho riscontrato questo stesso problema. Volevo generare un metodo piuttosto grande e spesso volevo "scambiare" per memorizzare un valore calcolato. Non ero soddisfatto del grande volume di persone del luogo che si presentavano in ildasm e ho notato che BeginScope/EndScope non era di alcun aiuto. Ho finito per creare uno 'swap' locale per il contesto del mio metodo e riutilizzarlo per ogni operazione di scambio. Rende il pulitore IL generato; non sono sicuro se abbia un impatto significativo sulle prestazioni.

Problemi correlati