Я скомпилировал некоторый тестовый код в режиме отладки и отразил полученную сборку с помощью ILSpy. Это IL, который я получаю:
.class private auto ansi beforefieldinit ArrayListBoxAndUnBox.Program
extends [mscorlib]System.Object
{
// Nested Types
.class nested public auto ansi beforefieldinit Point
extends [mscorlib]System.Object
{
// Fields
.field public int32 x
.field public int32 y
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x209f
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Point::.ctor
} // end of class Point
// Methods
.method private hidebysig static
void Main (
string[] args
) cil managed
{
// Method begins at RVA 0x2050
// Code size 59 (0x3b)
.maxstack 2
.entrypoint
.locals init (
[0] class [mscorlib]System.Collections.ArrayList list,
[1] int32 i,
[2] class ArrayListBoxAndUnBox.Program/Point p
)
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: box [mscorlib]System.Int32
IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_0013: pop
IL_0014: ldloc.0
IL_0015: ldc.i4.0
IL_0016: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
IL_001b: unbox.any [mscorlib]System.Int32
IL_0020: stloc.1
IL_0021: ldloc.0
IL_0022: newobj instance void ArrayListBoxAndUnBox.Program/Point::.ctor()
IL_0027: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_002c: pop
IL_002d: ldloc.0
IL_002e: ldc.i4.1
IL_002f: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
IL_0034: castclass ArrayListBoxAndUnBox.Program/Point
IL_0039: stloc.2
IL_003a: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2097
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class ArrayListBoxAndUnBox.Program
Я вижу, что для .maxstack установлено значение два, но когда я просматриваю код вручную, я иногда получаю 3 элемента в оценочном стеке. Почему? Я плохой IL-счетчик стека или в этом есть смысл?
В моем мире первый ldloc.0 в IL_0014 никогда не удаляется, но, возможно, это только я не понимаю, как работает callvirt для get_Item. Когда я дохожу до IL_0014, мне нужно указать ссылки на свой лист стека, и после этого в IL_0015 программа нарушает .maxstack, когда 0 помещается в стек оценки.
Я новичок, поэтому должно быть что-то не так. Может быть, мои подсчеты верны, а мое понимание .maxstack неверно, а может быть, все наоборот. Может ли кто-нибудь сказать мне, если я неправильно понимаю .maxstack, что .maxstack показывает максимальное количество элементов в стеке во время выполнения. Или если мой подсчет неверен? Удаляет ли Add ссылку на экземпляр списка?
РЕДАКТИРОВАТЬ: Вот как я считаю. Счет ведется после запуска кода IL:
IL_0000: 0 on stack
IL_0001: 1 on stack (the reference to array list)
IL_0006: 0 on stack
IL_0007: 1 on stack (the reference to arraylist)
IL_0008: 2 on stack (reference to arraylist and int 1)
IL_0009: 2 on stack (refernce to arraylist and reference to object that wrap 1)
IL_000e: 2 on stack (reference to arraylist and index to the added boxed int object)
IL_0013: 1 on stack (reference to arraylist)
IL_0014: 2 on stack (reference to arraylist and reference to arraylist)
IL_0015: 3 on stack (reference to arraylist and reference to arraylist and int 0)
Остальное я не считал, потому что знаю, что ошибаюсь.
Спасибо
callvirt
извлекает цель и аргументы из стека? См. раздел III.4.2 документа ECMA-335. - person Jon Skeet   schedule 24.10.20130e
выталкивает как ссылку на массив, так и номер, а затем выталкиваетInt32
- вот где вы ошиблись, вы не заметили, что ссылка на массив была извлечена. - person Tim S.   schedule 25.10.2013