Поделиться через


readonly (справочник по C#)

Ключевое readonly слово является модификатором, который можно использовать в пяти контекстах:

  • В объявлении поляreadonly указывает, что присвоение значений полю может происходить только в рамках объявления или в конструкторе того же класса. Поле чтения можно назначить и переназначить несколько раз в объявлении поля и конструкторе.

    Поле readonly не может быть установлено после выхода конструктора. Это правило имеет различные последствия для типов значений и ссылочных типов:

    • Так как типы значений непосредственно содержат их данные, поле, которое является типом readonly значения, является неизменяемым.
    • Так как ссылочные типы содержат ссылку на их данные, поле, которое является ссылочным типом readonly , всегда должно ссылаться на один и тот же объект. Этот объект может быть неизменяемым. Модификатор readonly предотвращает замену значения поля другим экземпляром ссылочного типа. Однако модификатор не предотвращает изменение данных экземпляра поля через поле, доступное только для чтения.

    Предупреждение

    Внешне видимый тип, содержащий внешне видимое только для чтения поле, которое является изменяемым ссылочным типом, может быть уязвимостью безопасности и может вызвать предупреждение CA2104: "Не объявляйте изменяемые ссылочные типы как только для чтения."

  • В определении типа readonly struct, readonly указывает на то, что тип структуры является неизменяемым. Дополнительные сведения см. в readonly разделе структуры статьи "Типы структур ".

  • В объявлении члена экземпляра типа структуры readonly указывает, что член экземпляра не изменяет состояние этой структуры. Дополнительные сведения см. в readonly разделе "Члены экземпляра " статьи "Типы структур ".

  • В возвращаемом методеref readonlyreadonly модификатор указывает, что метод возвращает ссылку и записи не допускаются к этой ссылке.

Пример поля readonly

В этом примере значение поля year нельзя изменить в методе ChangeYear, несмотря на то, что оно было присвоено значение в конструкторе классов:

class Age
{
    private readonly int _year;
    Age(int year)
    {
        _year = year;
    }
    void ChangeYear()
    {
        //_year = 1967; // Compile error if uncommented.
    }
}

Значение можно назначить полю readonly только в следующих контекстах:

  • При инициализации переменной в объявлении, например:

    public readonly int y = 5;
    
  • В конструкторе экземпляра класса, содержащего объявление поля экземпляра.

  • В статическом конструкторе класса, который содержит объявление статического поля.

Эти контексты конструктора также являются единственными контекстами, в которых допустимо передать readonly поле в качестве параметра out или ref .

Замечание

Ключевое readonly слово отличается от ключевого слова const . Инициализация поля const возможна только при его объявлении. Поле readonly можно назначить несколько раз в объявлении поля и в любом конструкторе. Таким образом, readonly поля могут иметь разные значения в зависимости от используемого конструктора. Кроме того, в то время как const поле является константой времени компиляции, readonly поле можно использовать для констант времени выполнения, как показано в следующем примере:

public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;
public class SamplePoint
{
    public int x;
    // Initialize a readonly field
    public readonly int y = 25;
    public readonly int z;

    public SamplePoint()
    {
        // Initialize a readonly instance field
        z = 24;
    }

    public SamplePoint(int p1, int p2, int p3)
    {
        x = p1;
        y = p2;
        z = p3;
    }

    public static void Main()
    {
        SamplePoint p1 = new SamplePoint(11, 21, 32);   // OK
        Console.WriteLine($"p1: x={p1.x}, y={p1.y}, z={p1.z}");
        SamplePoint p2 = new SamplePoint();
        p2.x = 55;   // OK
        Console.WriteLine($"p2: x={p2.x}, y={p2.y}, z={p2.z}");
    }
    /*
     Output:
        p1: x=11, y=21, z=32
        p2: x=55, y=25, z=24
    */
}

В предыдущем примере, если вы используете инструкцию, как показано в следующем примере:

p2.y = 66;        // Error

Вы получите сообщение об ошибке компилятора:

Поле только для чтения невозможно присвоить значение, за исключением конструктора и инициализатора переменной

Члены экземпляра только для чтения

Вы также можете использовать модификатор readonly, чтобы объявить, что член экземпляра не изменяет состояние структуры.

public readonly double Sum()
{
    return X + Y;
}

Замечание

В случае свойства чтения/записи можно добавить модификатор readonly к аксессору get. Некоторые get методы доступа могут выполнять вычисление и кэшировать результат, а не просто возвращать значение частного поля. readonly Добавление модификатора get в метод доступа гарантирует, что get метод доступа не изменяет внутреннее состояние объекта путем кэширования любого результата.

Дополнительные примеры см. в readonly разделе членов экземпляра статьи "Типы структур ".

Пример возврата ссылки только для чтения

Модификатор readonly на объекте ref return указывает, что возвращаемая ссылка не может быть изменена. В следующем примере возвращается ссылка на источник. Он использует readonly модификатор, чтобы указать, что вызывающие не могут изменить источник:

private static readonly SamplePoint s_origin = new SamplePoint(0, 0, 0);
public static ref readonly SamplePoint Origin => ref s_origin;

Возвращаемый тип не должен быть readonly struct. Любой тип, который можно вернуть с помощью ref, можно вернуть с помощью ref readonly.

Пример использования readonly ref возвращаемого значения readonly

Можно ref readonly return также использовать с readonly элементами экземпляра в struct типах:

public struct ReadonlyRefReadonlyExample
{
    private int _data;

    public readonly ref readonly int ReadonlyRefReadonly(ref int reference)
    {
        // _data = 1; // Compile error if uncommented.
        return ref reference;
    }
}

Метод по сути возвращает ссылку readonly вместе с членом экземпляра (в данном случае методом) readonly (не удается изменить поля экземпляра).

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является авторитетным источником синтаксиса и использования языка C#.

Вы также можете просмотреть предложения спецификации языка:

См. также