Одним из основных преимуществ типов значений, таких как Rectangle
, является то, что если у вас есть n хранилищ типа Rectangle
, можно быть уверенным, что у каждого есть n различных экземпляроввведите Rectangle
.Если у одного есть массив MyArray
типа Rectangle
, длиной не менее двух, оператор, подобный MyArray[0] = MyArray[1]
, скопирует поля MyArray[1]
в поля MyArray[0]
, но они будут продолжать ссылаться на отдельные Rectangle
экземпляров.Если затем выполнить строку оператора MyArray[0].X += 4
, которая изменит поле X
одного экземпляра без изменения значения X
любого другого слота массива или экземпляра Rectangle
.Кстати, обратите внимание, что при создании массива он мгновенно заполняется доступными для записи Rectangle
экземплярами.
Представьте себе, если Rectangle
был изменяемым типом класса.Создание массива изменяемых Rectangle
экземпляров потребовало бы, чтобы одно первое измерение массива, а затем назначил каждому элементу в массиве новый Rectangle
экземпляр.Если бы кто-то хотел скопировать значение одного экземпляра прямоугольника в другой, ему нужно было бы сказать что-то вроде MyArray[0].CopyValuesFrom(MyArray[1])
[что, конечно, не сработало бы, если бы MyArray[0]
не было заполнено ссылкой на новый экземпляр).Если кто-то случайно скажет MyArray[0] = MyArray[1]
, то запись в MyArray[0].X
также повлияет на MyArray[1].X
.Противные вещи.
Важно отметить, что в C # и vb.net есть несколько мест, где компилятор неявно копирует тип значения, а затем действует на копию, как если бы это был оригинал.Это действительно неудачный языковой дизайн, который побудил некоторых людей выдвинуть предположение, что типы значений должны быть неизменяемыми (поскольку большинство ситуаций, связанных с неявным копированием, вызывают проблемы только с изменяемыми типами значений).Когда компиляторы очень плохо предупреждали о случаях, когда семантически сомнительные копии приводили к нарушению поведения, такое представление могло быть разумным.Однако сегодня его следует считать устаревшим, учитывая, что любой приличный современный компилятор будет отмечать ошибки в большинстве сценариев, где неявное копирование приведет к нарушению семантики, включая все сценарии, в которых структуры изменяются только с помощью конструкторов, установщиков свойств или внешних назначений общедоступным изменяемым полям.,Выражение типа MyArray[0].X += 5
гораздо более читабельно, чем MyArray[0] = new Rectangle(MyArray[0].X + 5, MyArray[0].Y, MyArray[0].Width, MyArray[0].Height)
.