← Назад к вопросам

Что такое readonly поле?

1.0 Junior🔥 192 комментариев
#ООП и паттерны проектирования#Основы C# и .NET

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое поле readonly в C#

readonly — это модификатор, который можно применять к полям класса или структуры в C#. Его ключевая функция — разрешить присвоение значения полю только во время инициализации (в месте объявления) или в конструкторе того же класса/структуры. После этого, на протяжении всего времени существования объекта, значение этого поля изменить нельзя.

Основные особенности и правила

  • Инициализация: Значение полю readonly должно быть присвоено либо при его объявлении, либо в конструкторе (или в инициализаторе) того же класса. Попытка присвоить значение в любом другом методе (кроме конструктора) приведет к ошибке компиляции.
  • Изменяемость значения: Важно понимать разницу между неизменностью ссылки и неизменностью объекта. Если readonly поле является ссылочным типом (например, List<T>), то сама ссылка не может быть изменена (нельзя переназначить на другой объект), но состояние самого объекта, на который она указывает, может меняться (можно добавлять или удалять элементы из списка).
  • Статические readonly поля: Модификатор readonly также можно применять к статическим полям (static readonly). В этом случае инициализация должна происходить либо при объявлении, либо в статическом конструкторе (static constructor).
  • Область видимости: readonly не влияет на область видимости поля (public, private и т.д.). Он лишь контролирует присваивание.

Отличия от const

Часто возникает вопрос о разнице между readonly и const. Вот ключевые отличия:

  • Время вычисления значения: Поле const является константой времени компиляции. Его значение должно быть известно на этапе компиляции и подставляется непосредственно в IL-код. Поле readonly — это константа времени выполнения. Его значение вычисляется и присваивается при создании экземпляра класса (или при первой загрузке типа для static readonly).
  • Типы данных: Поле const может быть только примитивным типом (int, string, double и т.д.), перечислением (enum) или ссылкой на null. Поле readonly может быть любого типа, включая сложные пользовательские классы.
  • Статичность: Поле const неявно является статическим (static), поэтому доступ к нему осуществляется через имя типа. Поле readonly по умолчанию является экземплярным, если явно не объявлено как static.

Практические примеры

Пример 1: Базовое использование

public class Configuration
{
    // Инициализация при объявлении
    public readonly string DatabaseName = "DefaultDB";

    // Объявление без инициализации
    public readonly int Port;

    // Конструктор - единственное место, кроме объявления, где можно присвоить значение
    public Configuration(int portNumber)
    {
        this.Port = portNumber;
        // this.DatabaseName = "NewDB"; // Можно, но уже было инициализировано
    }

    public void TryToChange()
    {
        // Port = 8080; // ОШИБКА КОМПИЛЯЦИИ: Поле, доступное только для чтения `Port` может быть присвоено только в конструкторе или инициализаторе переменных
    }
}

Пример 2: Ссылочные типы

public class ServiceManager
{
    // Ссылка на список не может быть изменена, но сам список - может
    public readonly List<string> LogMessages = new List<string>();

    public void AddLog(string message)
    {
        LogMessages.Add(message); // Это допустимо
    }

    public void ReplaceLog()
    {
        // LogMessages = new List<string>(); // ОШИБКА КОМПИЛЯЦИИ: нельзя изменить ссылку
    }
}

Пример 3: Статическое readonly поле (альтернатива const для сложных типов)

public class AppConstants
{
    // Значение вычисляется при запуске приложения, в статическом конструкторе
    public static readonly DateTime AppStartTime = DateTime.Now;

    // Для типов, которые нельзя использовать с const (например, TimeSpan)
    public static readonly TimeSpan CacheTimeout = TimeSpan.FromMinutes(30);

    // Статический конструктор для инициализации
    static AppConstants()
    {
        // Здесь также можно инициализировать статические readonly поля
    }
}

Когда использовать readonly

  1. Для создания неизменяемых (immutable) структур данных: В сочетании с инициализацией только в конструкторе, readonly поля помогают создавать объекты, состояние которых не меняется после создания. Это ключевой принцип для потокобезопасности и предсказуемости кода.
  2. Для хранения параметров, переданных в конструктор: Очень часто поля, которые инициализируются аргументами конструктора, помечаются как readonly, чтобы гарантировать, что они останутся неизменными на протяжении жизни объекта.
  3. В качестве улучшенной альтернативы const: Когда нужна константа, но ее значение является сложным типом (не примитивом) или должно вычисляться во время выполнения (например, настройка из конфигурационного файла).

Итог

readonly — это мощный инструмент для повышения надежности и ясности кода. Он явно указывает другим разработчикам (и компилятору), что значение поля не предназначено для изменения после инициализации объекта, что предотвращает случайные ошибки и делает контракт класса более понятным. Использование readonly полей является хорошей практикой при проектировании классов, особенно в предметно-ориентированном дизайне (DDD) и при работе с многопоточными приложениями.

Что такое readonly поле? | PrepBro