Для вышеперечисленных типов операций вы должны определить свою собственную изменяемую STRUCT . Изменяемые структуры могут создавать головную боль для авторов компиляторов, таких как Эрик Липперт, и есть некоторые досадные ограничения в том, как .net обрабатывает их, но, тем не менее, семантика изменяемых структур "Обычные старые данные" (структуры, в которых все поля являются открытыми и единственными публичные функции, которые пишут this
, являются конструкторами или вызываются исключительно из конструкторов) предлагают гораздо более четкую семантику, чем это может быть достигнуто с помощью классов.
Например, рассмотрим следующее:
struct Foo {
public int bar;
...other stuff;
}
int test(Action<Foo[]> proc1, Action<Foo> proc2)
{
foo myFoos[] = new Foo[100];
proc1(myFoos);
myFoos[4].bar = 9;
proc2(myFoos[4]); // Pass-by-value
return myFoos[4].bar;
}
Если предположить, что небезопасного кода нет и что переданные делегаты могут быть вызваны и вернутся за конечное время, что вернет test()
? Тот факт, что Foo
является структурой с открытым полем bar
, достаточен для ответа на вопрос: он вернет 9, независимо от того, что еще появляется в объявлении Foo
, и независимо от того, какие функции передаются в proc1
и proc2
. Если бы Foo
был классом, нужно было бы изучить все Action<Foo[]>
и Action<Foo>
, которые существуют или будут существовать, чтобы узнать, что вернет test()
. Определить, что Foo
является структурой с открытым полем bar
, гораздо проще, чем изучить все прошлые и будущие функции, которые могут быть переданы.
Методы структуры, которые изменяют this
, обрабатываются особенно плохо в .net, поэтому, если нужно использовать метод для изменения структуры, почти наверняка лучше использовать один из следующих шаблонов:
myStruct = myStruct.ModifiedInSomeFashion(...); // Approach #1
myStructType.ModifyInSomeFashion(ref myStruct, ...); // Approach #2
чем шаблон:
myStruct.ModifyInSomeFashion(...);
При условии, что каждый использует вышеуказанный подход к шаблонам, изменяющим структуру, однако, изменяемые структуры имеют преимущество, заключающееся в том, что они позволяют код, который является одновременно более эффективным и простым для чтения, чем неизменяемые структуры или неизменяемые классы, и гораздо менее подвержен проблемам, чем изменяемый классы. Для вещей, которые представляют совокупность значений без идентичности вне значений, которые они содержат, изменяемые типы классов часто являются наихудшими из возможных представлений.