Являются ли readonly структуры, которые должны быть неизменными, когда в массиве?

(Примечание. Этот пример кода требует С# 7.2 или новее, а Nuget System.Memory.

Предположим, что мы имеем a readonly struct следующим образом:

public readonly struct Test
{
    public Test(int value)
    {
        Value = value;
    }

    public int Value { get; }
}

Теперь поставьте его в массив:

var array = new Test[] { new Test(1) };

Console.WriteLine(array[0].Value); // Prints 1

Пока все хорошо. Вы не можете писать код для непосредственного изменения array[0].Value.

Теперь предположим, что мы делаем это:

array.AsSpan().AsBytes()[3] = 1;

Console.WriteLine(array[0].Value); // Prints 16777217

Итак, теперь мы изменили компонент Value структуры readonly в массиве.

Правильно ли это поведение?

Ответ 1

Правильно ли это поведение?

Да. Структура readonly не изменяет изменчивость переменной, которая содержит копию структуры! Элементы массива являются переменными, а переменные могут меняться.

Вам не нужно использовать С# 7.2, чтобы увидеть это. Целые числа неизменны; нет способа превратить целое число 3 в целое число 4. Скорее, вы замените содержимое переменной, содержащей 3, с помощью 4. Тот факт, что целые числа неизменяемы, не превращает переменные в константы. Тоже самое. Строка неизменна, как и int, но переменная, удерживающая ее, изменена.

Аналогично, поле readonly в структуре является ложью; это поле может быть изменено, поскольку структуры не имеют своего хранилища. См. Использует ли использование общедоступных полей readonly для неизменяемых структур? для получения дополнительной информации об этом.

(И, конечно, все изменчиво, если вы нарушаете правила языка и среды выполнения, используя отражение на высоком уровне доверия или небезопасный код.)