Когда что-то может быть видоизменено, оно приобретает чувство идентичности.
struct Person {
public string name; // mutable
public Point position = new Point(0, 0); // mutable
public Person(string name, Point position) { ... }
}
Person eric = new Person("Eric Lippert", new Point(4, 2));
Поскольку Person
является изменчивым, более естественно думать о изменении позиции Эрика , чем клонировании Эрика, перемещении клона и уничтожении оригинала . Обе операции успешно изменят содержимое eric.position
, но одна из них более интуитивна, чем другая. Аналогично, более интуитивно понятно передать Эрику (в качестве ссылки) методы его модификации. Давать метод клону Эрика почти всегда будет удивительно. Любой, кто хочет видоизменить Person
, должен не забыть попросить ссылку на Person
, иначе он поступит неправильно.
Если вы сделаете тип неизменным, проблема исчезнет; если я не могу изменить eric
, мне все равно, получу ли я eric
или клон eric
. В более общем смысле тип можно безопасно передавать по значению, если все его наблюдаемое состояние хранится в следующих членах:
- неизменное
- ссылочные типы
- безопасно передать по значению
Если эти условия выполняются, тогда изменяемый тип значения ведет себя как ссылочный тип, потому что мелкая копия все еще позволяет получателю изменять исходные данные.
Интуитивность неизменного Person
зависит от того, что вы пытаетесь сделать. Если Person
просто представляет набор данных о человеке, в этом нет ничего не интуитивного; Person
переменные действительно представляют абстрактные значения , а не объекты. (В этом случае, вероятно, было бы более уместно переименовать его в PersonData
.) Если Person
фактически моделирует самого человека, идея постоянного создания и перемещения клонов глупа, даже если вы избежали ловушки думать, что вы модифицируете оригинал. В этом случае, вероятно, было бы более естественным просто сделать Person
ссылочным типом (то есть классом).
Конечно, поскольку функциональное программирование научило нас, есть преимущества сделать все неизменным (никто не может тайно держаться за ссылку на eric
и изменять его), но поскольку это не идиоматично в ООП это все еще будет не интуитивно понятно любому, кто работает с вашим кодом.