C# оптимизирует перегруженные операторы
Вопрос
Кажется, единственным выходом является возврат нового объекта для перегруженных операторов.Верно?
- Если у вас есть класс (X), содержащий большой буфер
- Часть буфера содержит контент, остальное свободно.
- Вы перегрузили двоичный оператор + для объединения двух объектов (одного типа), создав новый объект, содержащий добавленное содержимое обоих операндов.
Другими словами:
z = x + y // z is a new object containing the appended data from x and y.
Это, очевидно, хорошо, потому что мы не хотим искажать x или y во время операции.Однако в спецификациях языка C# 7.2.2 говорится:
Когда бинарный оператор перегружен, соответствующий оператор присваивания (если есть) также неявно перегружается.
это значит, что:
x += y; // will create a new x, copy contents of old x merged with y
// and the old x will be garbage collected at some point
Это болезненно, потому что гораздо быстрее можно было бы просто скопировать содержимое y в свободную часть x.Таким образом, мы не копируем большой объект и не оставляем беспорядок для хорошего сборщика мусора.
Я понимаю, что это можно сделать с помощью простого x.Add(y).Мне любопытно, есть ли способ сделать это с помощью операторов.например, чтобы выяснить, что мы находимся внутри оператора присваивания и выполнить оптимизированную процедуру.
Решение
Лично мне нравится, как это реализовано в C#.
Более «очевидно», что:
x += y;
и
x = x + y;
Должно иметь такое же поведение.В C# это реализовано.При раздельных перегрузках люди могут злоупотреблять оператором и препятствовать тому, чтобы он действовал одинаково.
Разница в производительности будет настолько минимальной, что также облегчит реализацию и поддержку, поэтому я настоятельно предпочитаю подход C#.
Другие советы
Все математические бинарные операторы возвращают новый объект.Например.Вы бы не хотели, чтобы 2+3 изменило значение одного из них на пять только потому, что вы их складывали.Другими словами, семантика рассматриваемых операторов очень ясна и закреплена в спецификациях.Если вы хотите чего-то другого, вам придется сделать что-то другое :).И мне лично это нравится по сравнению с C++, где вы можете сделать перегрузку, например, A=B=C может привести к удалению C, неназначению B и присвоению A любого значения, независимо от C или B.