Если вы собираетесь использовать структуры, рекомендуется сделать их неизменяемыми.
Создание всех полей только для чтения - это отличный способ помочь (1) документировать, что структура неизменна, и(2) предотвратить случайные мутации.
Однако, есть одна морщина, которая на самом деле по странному совпадению я планировал вести в блоге на следующей неделе.То есть: только для чтения в поле структуры - ложь .Можно ожидать, что поле только для чтения не может измениться, но, конечно, может.«только для чтения» в поле структуры - это чек для написания декларации без денег на его счете. Структура не владеет своим хранилищем, и это хранилище может изменяться.
Например, давайте возьмем вашу структуру:
public struct Pair
{
public readonly int x;
public readonly int y;
public Pair(int x, int y)
{
this.x = x;
this.y = y;
}
public void M(ref Pair p)
{
int oldX = x;
int oldY = y;
// Something happens here
Debug.Assert(x == oldX);
Debug.Assert(y == oldY);
}
}
Есть ли что-нибудьчто может произойти при «что-то здесь происходит», что приводит к нарушению отладочных утверждений?Конечно.
public void M(ref Pair p)
{
int oldX = this.x;
int oldY = this.y;
p = new Pair(0, 0);
Debug.Assert(this.x == oldX);
Debug.Assert(this.y == oldY);
}
...
Pair myPair = new Pair(10, 20);
myPair.M(ref myPair);
И что теперь происходит?Утверждение нарушено!«this» и «p» относятся к одному и тому же месту хранения.Место хранения видоизменено, и поэтому содержимое «этого» видоизменено, потому что это одно и то же.Структура не может обеспечить доступность только для чтения x и y, потому что структура не владеет хранилищем;хранилище - это локальная переменная, которая может изменять любое количество раз.
Вы не можете полагаться на инвариант, что поле readonly никогда не изменяется;единственное, на что вы можете положиться, это то, что вы не можете написать код, который напрямую его изменяет.Но с помощью такой хитрой работы вы можете косвенно изменить все, что вы хотите.
См. Также отличную статью Джо Даффи в блоге по этому вопросу:
http://joeduffyblog.com/2010/07/01/when-is-a-readonly-field-not-readonly/