Ключ в понимании того, как работает строка Account b = a++;
. Учитывая, как написан ваш код, эта строка эквивалентна этому:
Account b = a;
a++;
И это порядок, в котором он будет выполняться. Назначение эффективно (1) происходит до приращения. Итак, первый эффект этой строки состоит в том, что a и b оба ссылаются на исходный объект a .
Теперь часть ++ будет оценена. Внутри операторного метода мы увеличиваем Balance
исходного объекта. В этот момент a и b оба указывают на оригинал с Balance
, равным 11, и b будет продолжать это делать.
Однако вы создали новый объект внутри метода оператора и вернули его в качестве вывода оператора. a теперь будет обновлено, чтобы указывать на вновь созданный объект.
Итак, a теперь указывает на новый объект, а b продолжает указывать на оригинал. Вот почему вывод WriteLine выглядит поменянным.
Как указал @MarkusQ, оператор ++ предназначен для изменения на месте. Генерируя новый объект, вы нарушаете это предположение. Перегрузка операторов объектами - сложная тема, и это отличный пример того, почему ее лучше избегать в большинстве случаев.
1 - Просто ради точности, присвоение фактически не происходит до приращения при работе с операторами на объектах, но конечный результат в этом случае тот же. Фактически, исходная ссылка на объект копируется, операция выполняется с исходной, а затем скопированная ссылка присваивается левой переменной. Проще объяснить, если вы притворяетесь, что назначение происходит первым.
Что действительно происходит, так это:
Account b = a++;
это приводит к тому, как оператор ++ работает с объектами:
Account copy = a;
Account x = new Account("operator ++", a.Balance);
a.Balance += 1; // original object's Balance is incremented
a = x; // a now points to the new object, copy still points to the original
Account b = copy; // b and copy now point at the same, original, object