Ни одна из ваших выведенных пошаговых процедур не верна в отношении скомпилированного вывода. CLR является машиной стека, и поскольку код для добавления всех четырех сразу не указывает на необходимость отдельного выделения промежуточных итогов в качестве именованных переменных, он обновляет промежуточную сумму на месте (или, скорее, выдает и помещает верхний элемент стека).
Обе ваши пошаговые версии требуют одинакового количества реальных операций; версия с унарным сложением просто требует на одну локальную переменную меньше.
Ниже приведен фактический IL, полученный тремя различными способами сложения четырех входных комплексных чисел. Обратите внимание, что в моей версии я изменил класс Complex (который, как я полагаю, вы подняли с Как: использовать перегрузку оператора для создания класса комплексных чисел (Руководство по программированию в C #) ), чтобы хранить два значения double
вместо двух int
s. Я пропустил объявление c1..c4 в коде C # и IL для краткости. Короче говоря, оба выведенных пошаговых подхода требуют по два дополнительных вызова stloc.s
(отправка значения в список переменных) и ldloc.s
(получение значения из списка переменных) каждый.
Оригинал: Добавить все четыре в ряд:
C #:
Complex csum = c1 + c2 + c3 + c4;
IL:
// MultipleAdd : 5 Locals, maxstack 3
IL_0068: nop
IL_0069: ldloc.0
IL_006a: ldloc.1
IL_006b: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0070: ldloc.2
IL_0071: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0076: ldloc.3
IL_0077: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_007c: stloc.s csum
IL_007e: ret
Вывод 1: три двоичных дополнения
C #:
Complex ct1 = c1 + c2;
Complex ct2 = ct1 + c3;
Complex csum = ct2 + c4;
IL:
// BinaryAdd : 7 Locals, maxstack 3
IL_0068: nop
IL_0069: ldloc.0
IL_006a: ldloc.1
IL_006b: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0070: stloc.s ct1
IL_0072: ldloc.s ct1
IL_0074: ldloc.2
IL_0075: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_007a: stloc.s ct2
IL_007c: ldloc.s ct2
IL_007e: ldloc.3
IL_007f: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0084: stloc.s csum
IL_0086: ret
Вывод 2: Унарные дополнения
C #:
Complex ct = c1 + c2;
ct += c3;
Complex csum = ct + c4;
IL:
// UnaryAdd : 6 Locals, maxstack 3
IL_0068: nop
IL_0069: ldloc.0
IL_006a: ldloc.1
IL_006b: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0070: stloc.s ct
IL_0072: ldloc.s ct
IL_0074: ldloc.2
IL_0075: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_007a: stloc.s ct
IL_007c: ldloc.s ct
IL_007e: ldloc.3
IL_007f: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0084: stloc.s csum
IL_0086: ret