Должны ли структуры readonly быть неизменными в массиве?

(Примечание. Для этого примера кода требуется C# 7.2 или более поздняя версия и пакет Nuget System.Memory.)

Давайте предположим, что у нас есть 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 компонент структуры только для чтения в массиве.

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

1 ответ

Решение

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

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

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

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

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

Другие вопросы по тегам