Например, есть массив с элементами.
int [] numbers = new int[] { 1, 2, 3, 4, 5 };
for (int i = 0; i < numbers.Length; ++i)
{
Console.WriteLine(numbers[i]);
}
Открыв ILSpy, обнаружил что (++i)преинкремент стал постинкриментом(i++), хотя казалось бы, должно быть наоборот.
number.Length высчитывается 1 раз или при каждой итерации??(по идее каждый раз, но мало ли среда как-то это оптимизирует)
Есть ли смысл выносить условие в отдельную переменную перед циклом?
Ответ
Вы смотрите не туда.
Реальной оптимизацией занимается 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# как постинкремент, это исключительно для удобства читателей (постинкремент привычнее).
Ну и финальный совет: нет никаких письменных правил (кроме личного опыта) по поводу того, что быстро, а что медленно. Хуже того, любые «правила» с выходом новой версии компилятора станут скорее всего неправильными: оптимизаторы улучшаются каждый день. Поэтому:
старайтесь писать так, чтобы ваш код был читаем, не увлекайтесь нанооптимизациями,
профилируйте ваш код регулярно и устраняйте bottleneck'и.
*Как правильно подсказывает в комментариях @PetSerAl, разница между пре- и постинкрементом в C# (в отличие от C++) состоит лишь в том, какое значение возвращается выражением. Поэтому для случая, когда результатом инкремента никто не пользуется, их смысл всегда одинаков (для любого типа, не только для int).
Комментариев нет:
Отправить комментарий