ldelem.ref помещает ссылку на элемент массива в стек.Это означает, что он делает его копию, а не фактическую сохраненную ссылку.Может быть полезно прочитать документацию System.Reflection.Emit , чтобы понять больше.
Еще одна вещь, которая может быть полезна для понимания, состоит в том, что каждая инструкция MSIL требует N значений из стека, гдеN определяется конкретной используемой инструкцией (среди прочего).Затем это можно использовать для умственной группировки вещей для более легкого понимания.
IL_0002: ldarg.0
IL_0003: ldc.i4.0
IL_0004: ldelem.ref
ldelem.ref требует, чтобы в стеке имелся следующий порядок: ссылка на массив, индекс в этом массиве.Это вытолкнет эти значения, а затем поместит ссылку в стек.Стек теперь содержит одну вещь.
IL_0005: stloc.0
Единственное значение в стеке теперь извлекается и помещается в локальное хранилище.Стек пуст.
IL_0006: ldloc.0
IL_0007: ldstr "del"
IL_000c: call bool [mscorlib]System.String::op_Equality(string, string)
Команда вызова вытолкнет столько элементов в стеке, сколько и параметров (включая экземпляр, если вызванный метод является методом экземпляра).В этом случае ему нужны два строковых параметра, и они будут извлекать как содержимое локальной переменной, так и буквенную строку «del».Статический метод op_Equality возвращает тип bool, поэтому он будет помещен в стек.Стек теперь содержит одну вещь.
IL_0011: stloc.1
Единственное значение в стеке теперь извлекается и помещается в локальное хранилище.Стек пуст.
IL_0012: ldloc.1
IL_0013: brfalse.s IL_004e
Затем загружается значение и применяется логика ветвления.
В C # MSIL выполняет нечто эквивалентное следующему:
if (array[0] == "del")
Все в MSIL - это балансирование.Из-за того, что это отладочная сборка, может быть больше nop-инструкций и больше использования локальных компьютеров, чем оптимизированной сборки (что хорошо для вас, потому что вы можете немного легче следить за вещами).