Qual è il punto di NOP in CIL

Così ho scritto il seguente codice in C #.

class Test { int a; System.IO.StreamReader reader; public Test() { a = 5; reader = new System.IO.StreamReader(String.Empty); } } 

E il costruttore della class in IL assomiglia a questo

 .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 33 (0x21) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: ldc.i4.5 IL_000a: stfld int32 Test2.Test::a IL_000f: ldarg.0 IL_0010: ldsfld string [mscorlib]System.String::Empty IL_0015: newobj instance void [mscorlib]System.IO.StreamReader::.ctor(string) IL_001a: stfld class [mscorlib]System.IO.StreamReader Test2.Test::reader IL_001f: nop IL_0020: ret } // end of method Test::.ctor 

Ci sono 3 comandi nop . (Che come so non significa nessuna operazione). Qual è la necessità di quei comandi. Voglio dire quale sarebbe la differenza se non ci fosse alcun comando al posto di nop

Vengono utilizzati dal compilatore C # quando scrive il file .pdb per il programma. Che contiene informazioni di debug, che includono le informazioni sul numero di riga + del file per il tuo codice. Il debugger usa questo per trovare il codice macchina dove deve iniettare un’istruzione INT 3 per far sì che il programma smetta di funzionare quando si imposta un punto di interruzione. Il jitter emette un’istruzione NOP per codice macchina per ogni Opcodes. Nulla in MSIL.

Il primo nop viene utilizzato quando si imposta un punto di interruzione su public Test() . Si noti che viene iniettato dopo la chiamata del costruttore di base in modo che la variabile diventi valida nelle windows di debug di Auto / Locals / Watch.

Il secondo nop viene utilizzato quando si imposta un punto di interruzione sul primo {parentesi graffa. Quella linea non genera alcun codice quindi c’è un forte bisogno di un’istruzione MSIL falsa.

Stessa storia per il terzo nop, generato per l’ultimo} parentesi graffa. Quando si imposta un punto di interruzione su quello, è ansible esaminare il valore di ritorno del metodo (se presente). Visibile indirettamente nella finestra Debug + Windows + Registers. Migliorato in VS2013.

Quindi questo aiuta solo a fare il debug del tuo programma, fanno agire i breakpoint in modo prevedibile. Questi NOP non vengono generati quando si crea la configurazione di rilascio del programma. Uno dei motivi principali per cui un progetto C # ha una configurazione di debug e release. Puoi ancora eseguire il debug di una build Release, è comunque un’esperienza piuttosto confusa che ti fa dubitare della tua sanità mentale 🙂

Vengono utilizzati per supportare i punti di interruzione durante la creazione in modalità di debug e non fanno alcuna differenza nell’esecuzione dell’assembly.