So I wrote the following code in C#.
class Test
{
int a;
System.IO.StreamReader reader;
public Test()
{
a = 5;
reader = new Sys
They are used by the C# compiler when it writes the .pdb file for your program. Which contains debugging info, which includes file+line number info for your code. The debugger uses this to find the machine code where it needs to inject an INT 3
instruction to get the program to stop executing when you set a breakpoint. The jitter emits a NOP machine code instruction for each Opcodes.Nop in the MSIL.
The first nop is used when you set a breakpoint on public Test()
. Note that it is injected after the base constructor call so that the this variable becomes valid in the Auto/Locals/Watch debugging windows.
The second nop is used when you set a breakpoint on the first { curly brace. That line generates no code at all so there's a hard need for a fake MSIL instruction.
Same story for the third nop, generated for the last } curly brace. When you set a breakpoint on that one then you can inspect the method return value (if any). Visible indirectly in the Debug + Windows + Registers window. Improved in VS2013.
So this just aids in debugging your program, they make breakpoints act predictably. Those NOPs are not generated when you build the Release configuration of your program. One big reason why a C# project has a Debug and a Release configuration. You can still debug a Release build, it is however a pretty confounding experience that makes you doubt your sanity :)
They are used to support breakpoints when building in debug mode and will make no difference to the execution of your assembly.