Почему только для чтения членов в структуре, но не в классе - PullRequest
4 голосов
/ 01 мая 2020

C# 8.0 представил readonly членов в структуре (как объяснено здесь ). Например, у вас может быть такой метод:

public readonly override string ToString() => $"({X}, {Y}) is {Distance} from the origin";

Кроме того, если ваш метод readonly изменяет состояние структуры, он не будет компилироваться - что я считаю довольно полезным и элегантным решением. Так, например, в приведенном ниже примере, если X и Y являются свойствами структуры, следующий метод не будет компилироваться:

public readonly void Translate(int xOffset, int yOffset)
{
    X += xOffset;
    Y += yOffset;
}

Опять же, очень полезный и элегантный способ express Намерение кода.

Почему тогда это возможно только для структур, а не для классов. Если я пытаюсь добавить readonly к методу в классе, я получаю ошибку компилятора: The modifier 'readonly' is not valid for this item.

Существуют ли какие-либо ограничения ссылочного типа, когда использование метода только для чтения не имеет смысла?

1 Ответ

1 голос
/ 01 мая 2020

По моему мнению, есть две причины, по которым C# 8.0 предоставляет только read-only членов для структур:
1. Структуры являются типами значений . Когда вы вызываете метод и передаете структуру в качестве параметра, компилятор создает глубокую копию экземпляров структуры. Как показывает документация :

public static class MyClass
{
    public static float ExistingBehavior(in Vector2 vector)
    {
        return vector.GetLength();
    }

    public static float ReadonlyBehavior(in Vector2 vector)
    {
        return vector.GetLengthReadonly();
    }
}

Здесь vector - это структура. По умолчанию при вызове метода ExistingBehavior компилятор создает скрытую копию класса vector. До C# 8.0, делая всю структуру vector доступной только для чтения, было бы предотвращено скрытое копирование, что при определенных c обстоятельствах могло бы привести к преимуществам производительности . Но что, если не вся структура неизменна? Теперь, с новой функцией в C# 8.0, можно сделать только указанный метод c только для чтения и предотвратить создание скрытой копии компилятором. Для ссылочных типов, таких как классы и интерфейсы, нет никакого преимущества в производительности, так как экземпляр передается по ссылке, а скрытая копия не создается Поэтому нет смысла добавлять эту функцию в классы и интерфейсы.
2. Другая причина заключается в том, что это расширение концепции структур только для чтения, но не существует интерфейсов или классов только для чтения.

...