Например, есть массив с элементами.
int [] numbers = new int[] { 1, 2, 3, 4, 5 };
for (int i = 0; i < numbers.Length; ++i)
{
Console.WriteLine(numbers[i]);
}
Вы смотрите не туда.
Реальной оптимизацией занимается JIT-компилятор, а он довольно умный. Для вашего кода, он произвёл следующий объектный код (разумеется, Release-режим и без отладчика):
00007FF88B8B04ED xor edi,edi ; i = 0
00007FF88B8B04EF movsxd rcx,edi
00007FF88B8B04F2 mov ecx,dword ptr [rsi+rcx*4+10h] ; ecx = numbers[i]
00007FF88B8B04F6 call 00007FF8E9C19E40 ; Console.WriteLine
00007FF88B8B04FB inc edi ; i++
00007FF88B8B04FD cmp edi,5 ; if (i < 5)
00007FF88B8B0500 jl 00007FF88B8B04EF ; repeat
Вы видите, что не только исчезла разница между пре- и пост-инкрементом, не только исчезло повторное чтение Length
, а ещё оптимизатор смог понять, что длина равна константе 5.
Поверьте, компиляторы справляются с нанооптимизациями куда лучше нас с вами.
На уровне IL-кода разницы между пре- и постинкрементом нет*:
IL_001e: ldloc.1
IL_001f: ldc.i4.1
IL_0020: add
IL_0021: stloc.1
То, что ILSpy декомпилировал эту последовательность команд на C# как постинкремент, это исключительно для удобства читателей (постинкремент привычнее).
Ну и финальный совет: нет никаких письменных правил (кроме личного опыта) по поводу того, что быстро, а что медленно. Хуже того, любые «правила» с выходом новой версии компилятора станут скорее всего неправильными: оптимизаторы улучшаются каждый день. Поэтому:
*Как правильно подсказывает в комментариях @PetSerAl, разница между пре- и постинкрементом в C# (в отличие от C++) состоит лишь в том, какое значение возвращается выражением. Поэтому для случая, когда результатом инкремента никто не пользуется, их смысл всегда одинаков (для любого типа, не только для int
).
Виртуальный выделенный сервер (VDS) становится отличным выбором
Доброго времени суток! При написании подсистемы тестирования пользовательских решений задач по программированию столкнулся с такой проблемой:
Добрый вечерЕсть вопрос, использую Angular Material для первого Angular'a