Какая точка nop в CIL

Итак, я написал следующий код в С#.

class Test
{
    int a;
    System.IO.StreamReader reader;

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

И конструктор класса в IL выглядит так:

.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

Есть 3 команды nop. (Что, как я знаю, не означает никакой операции). В чем нуждаются эти команды. Я имею в виду, какая разница, если вообще не было команды вместо nop

Ответ 1

Они используются компилятором С#, когда он записывает файл .pdb для вашей программы. Что содержит информацию об отладке, которая включает в себя информацию о файле + номер строки для вашего кода. Отладчик использует это, чтобы найти машинный код, где ему нужно ввести инструкцию INT 3, чтобы программа перестала выполняться при установке точки останова. Джиттер испускает команду кодового кода NOP для каждого Opcodes.Nop в MSIL.

Первый nop используется, когда вы устанавливаете точку останова на public Test(). Обратите внимание, что он вводится после вызова базового конструктора, чтобы эта переменная стала действительной в окнах отладки Auto/Locals/Watch.

Второй nop используется, когда вы устанавливаете точку останова на первой {фигурной скобке. Эта строка не генерирует никакого кода, поэтому существует жесткая потребность в поддельной инструкции MSIL.

Та же история для третьего nop, сгенерированного для последней} фигурной скобки. Когда вы устанавливаете точку останова на этом, вы можете проверить возвращаемое значение метода (если есть). Видимый косвенно в окне Debug + Windows + Registers. Улучшено в VS2013.

Таким образом, это просто помогает отлаживать вашу программу, они делают контрольные точки предсказуемыми. Эти NOP не генерируются при создании конфигурации Release вашей программы. Одна из серьезных причин, почему проект С# имеет конфигурацию Debug и Release. Вы все еще можете отлаживать сборку Release, но это довольно неприятный опыт, который заставляет вас сомневаться в своем здравом рассудке:)

Ответ 2

Они используются для поддержки точек останова при построении в режиме отладки и не имеют никакого значения для выполнения вашей сборки.