Ответ 1
Если вы собираетесь использовать структуры, лучше всего сделать их неизменными.
Создание всех полей readonly - отличный способ помочь (1) документу, что структура является неизменной и (2) предотвращает случайные мутации.
Однако есть одна морщина, которая на самом деле в странном совпадении я планировал вести блог о следующей неделе. То есть: readonly в поле struct является ложью. Можно ожидать, что поле readonly не может измениться, но, конечно, это возможно. "readonly" в поле struct - это декларация, которая записывает чеки без денег в своем аккаунте. Структура не имеет своего хранилища, и это хранилище, которое может мутировать.
Например, возьмите вашу структуру:
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" относятся к тому же месту хранения. Место хранения мутировано, поэтому содержимое "this" мутировано, потому что это одно и то же. Структура не может обеспечить доступность только для чтения x и y, поскольку структура не владеет хранилищем; хранилище - это локальная переменная, которая может мутировать столько, сколько захочет.
Вы не можете полагаться на инвариант, который никогда не наблюдается для поля readonly в структуре; единственное, на что вы можете положиться, это то, что вы не можете писать код, который его напрямую меняет. Но, немного подкрадывая эту работу, вы можете косвенно изменить все, что захотите.
См. также Джо Доффи отличную статью в блоге по этой проблеме:
http://joeduffyblog.com/2010/07/01/when-is-a-readonly-field-not-readonly/