У меня эти два куска кода в С#:
Первая
class Program
{
static Stack<int> S = new Stack<int>();
static int Foo(int n) {
if (n == 0)
return 0;
S.Push(0);
S.Push(1);
...
S.Push(999);
return Foo( n-1 );
}
}
Второй
class Program
{
static Stack S = new Stack();
static int Foo(int n) {
if (n == 0)
return 0;
S.Push(0);
S.Push(1);
...
S.Push(999);
return Foo( n-1 );
}
}
Оба они делают то же самое:
-
Создайте стек (общий для
<int>
для первого примера и стек объекта для второго). -
Объявите метод, который вызывает себя рекурсивно n раз (n >= 0), и на каждом шаге нажимайте 1000 целых чисел внутри созданного стека.
Когда я запускаю первый пример с Foo(30000)
, исключение не возникает, но второй пример сбрасывается с помощью Foo(1000)
, только n = 1000.
Когда я увидел CIL, сгенерированный для обоих случаев, единственной разницей была бокс-часть для каждого нажатия:
Первая
IL_0030: ldsfld class [System]System.Collections.Generic.Stack`1<int32> Test.Program::S
IL_0035: ldc.i4 0x3e7
IL_003a: callvirt instance void class [System]System.Collections.Generic.Stack`1<int32>::Push(!0)
IL_003f: nop
Второй
IL_003a: ldsfld class [mscorlib]System.Collections.Stack Test.Program::S
IL_003f: ldc.i4 0x3e7
IL_0044: box [mscorlib]System.Int32
IL_0049: callvirt instance void [mscorlib]System.Collections.Stack::Push(object)
IL_004e: nop
Мой вопрос: почему, если нет второстепенной перегрузки стека CIL для второго примера, происходит ли он "быстрее", чем первый?