Такие типы являются изменяемыми, потому что, вопреки тому, что некоторые люди могут утверждать, изменяемая семантика типа значения полезна .В некоторых местах .net пытается сделать вид, что типы значений должны иметь ту же семантику, что и ссылочные типы.Поскольку изменчивая семантика типа значения принципиально отличается от изменчивой семантики ссылочного типа, притворство, что они одинаковые, вызовет проблемы.Однако это не делает их «злыми» - это просто показывает недостаток в объектной модели, который предполагает, что действие на копию чего-либо будет семантически эквивалентно действию на оригинал.True, если рассматриваемая вещь является ссылкой на объект;в целом верно - но с исключениями - если это неизменная структура;false, если это изменяемая структура.
Одна из замечательных особенностей структур с открытыми полями заключается в том, что их семантика легко устанавливается даже при простом осмотре.Если у человека есть Point[100] PointArray
, у него есть 100 различных экземпляров Point
.Если кто-то скажет PointArray[4].X = 9;
, это изменит один пункт PointArray
, а не другой.
Предположим, что вместо использования struct Point
один имел изменяемый класс PointClass
:
class PointClass {public int X; public int Y;};
Сколько экземпляров PointClass хранится в PointClass[100] PointClassArray
?Есть ли способ сказать?Повлияет ли оператор PointClass[4].X = 9
на значение PointClass [2] .X?Как насчет someOtherObject.somePoint.X
?
Хотя коллекции .net не очень хорошо подходят для хранения изменяемых структур, я, тем не менее, считаю, что
Dictionary<string, Point>;
...
Point temp = myDict["George"];
temp.X = 9;
myDict["George"] = temp;
имеет относительно четкую семантику, по крайней мере, вотсутствие проблем с многопоточностью.Несмотря на то, что я сожалею, что коллекции .net не предоставляют средства, с помощью которого можно просто сказать myDict[lookupKey].X = 9;
, я все равно расценил бы приведенный выше код как довольно ясный и не требующий пояснений без необходимости знать что-либо оКроме того, укажите, что у него есть открытое целочисленное поле с именем X. Напротив, если бы у него было Dictionary<PointClass>
, было бы неясно, что нужно делать, чтобы изменить значение X, связанное с «Джорджем».Возможно, экземпляр PointClass
, связанный с Джорджем, больше нигде не используется, и в этом случае можно просто написать соответствующее поле.С другой стороны, также возможно, что кто-то другой захватил копию MyDict["George"]
с целью получения значений в ней, и не ожидает, что объект PointClass
, который он захватил, может измениться.
Некоторые люди могут подумать, что «точка» должна быть неизменной структурой, но эффект такого выражения, как somePoint.X = 5;
, может быть полностью определен, зная только, что somePoint
- это переменная типа Point
, которая, в свою очередь, является структурой спубличное поле int называется X
.Если бы Point
была неизменной структурой, вместо этого нужно было бы сказать что-то вроде somePoint = new Point(5, somePoint.Y);
, что, помимо того, что было бы медленнее, потребовало бы проверки структуры, чтобы определить, что все ее поля инициализируются в конструкторе, причем Xпервое и Y второе.В каком смысле это будет улучшение по сравнению с somePoint.X = 5;
?
Кстати, самая большая «ошибка» с изменяемыми структурами проистекает из того факта, что система не может отличить методы структуры, которые изменяют «это» отте, которые нет.Главный позор.Предпочтительными обходными путями являются либо использование функций, которые возвращают новые структуры, полученные из старых, либо использование статических функций, которые принимают параметры структуры «ref».