Одна вещь, чтобы иметь в виду, что локальные переменные, как правило, выделяется в стеке. Одна задача, которую должен выполнить компилятор, - это выяснить, сколько пространства стека требуется конкретному методу и отложить это.
Рассмотрим:
int Func(int a, int b, int c)
{
int x = a * 2;
int y = b * 3;
int z = c * 4;
return x + y + z;
}
Игнорируя тот факт, что это может быть легко оптимизированы для возврата (а * 2) + (б * 3) + (с * 4), компилятор будет увидеть три локальные переменные и выделить место для трех локальных переменных.
Если у меня есть это:
int Func(int a, int b, int c)
{
int x = a * 2;
{
int y = b * 3;
{
int z = c * 4;
{
return x + y + z;
}
}
}
}
Это все те же 3 локальные переменные - только в различных областях. Цикл for - это не что иное, как блок областей с небольшим кодом клея, чтобы заставить его работать.
Теперь рассмотрим это:
int Func(int a, int b, int c)
{
int x = a * 2;
{
int y = b * 3;
x += y;
}
{
int z = c * 4;
x += z;
}
return x;
}
Это единственный случай, когда он может быть разными. У вас есть переменные y и z, которые входят и выходят из области действия - после того, как они вышли из сферы действия, пространство стека больше не требуется. Компилятор может выбрать повторное использование этих слотов, так что y и z используют одно и то же пространство. Поскольку оптимизация идет, это просто, но это мало выигрывает - это экономит некоторое пространство, что может быть важно для встроенных систем, но не для большинства приложений .NET.
В качестве примечания, компилятор C# в VS2008 в выпуске даже не выполняет простейшие сокращения прочности. IL для первой версии это:
L_0000: ldarg.0
L_0001: ldc.i4.2
L_0002: mul
L_0003: stloc.0
L_0004: ldarg.1
L_0005: ldc.i4.3
L_0006: mul
L_0007: stloc.1
L_0008: ldarg.2
L_0009: ldc.i4.4
L_000a: mul
L_000b: stloc.2
L_000c: ldloc.0
L_000d: ldloc.1
L_000e: add
L_000f: ldloc.2
L_0010: add
L_0011: ret
в то время как я ожидал увидеть это:
L_0000: ldarg.0
L_0001: ldc.i4.2
L_0002: mul
L_0003: ldarg.1
L_0004: ldc.i4.3
L_0005: mul
L_0006: add
L_0007: ldarg.2
L_0008: ldc.i4.4
L_0009: mul
L_000a: add
L_000b: ret
'int's не являются объектами, поэтому создание их - это, вероятно, одна или две инструкции. Может быть, объект станет лучшим примером. –
Мне нравится второй подход.Зачем вам нужна эта дополнительная переменная? Кроме того, добавьте несколько пробелов в цикл for! –
И, наконец, всегда полезно сравнить полученный ИЛ и ПРОФИЛЬ! –