Константы и поля readonly
Различайте const и static readonly.
«Константы и поля readonly» — бесплатный урок C# Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Два способа сделать значения неизменяемыми
В C# доступны const и readonly для значений, которые не должны изменяться. Они выглядят похоже, но работают совершенно по-разному. В этом уроке сравниваются эти два подхода.
using System;
class Config
{
public const double Pi = 3.14159;
public static readonly DateTime StartedAt = DateTime.Now;
}
class Program
{
static void Main()
{
Console.WriteLine("Pi = " + Config.Pi);
}
}const: константа времени компиляции
const необходимо присвоить непосредственно заданное значение при объявлении; оно фиксируется во время компиляции. Такой член неявно является статическим.
using System;
class Circle
{
public const double Pi = 3.14159;
public static double Area(double r) => Pi * r * r;
}
class Program
{
static void Main()
{
Console.WriteLine(Circle.Area(2).ToString("0.00"));
}
}const должен быть литералом
Поскольку значение const определяется во время компиляции, оно может содержать только константное выражение: числа, строки, логические значения или другие константы.
using System;
class Limits
{
public const int MaxRetries = 3;
public const int Timeout = MaxRetries * 1000; // const expression OK
}
class Program
{
static void Main()
{
Console.WriteLine(Limits.MaxRetries + ", " + Limits.Timeout);
}
}readonly: константа времени выполнения
Поле readonly задаётся один раз — при объявлении или в конструкторе — и после этого не может изменяться. Его значение можно вычислить во время выполнения.
using System;
class Session
{
public readonly string Id;
public Session(string id)
{
Id = id; // allowed: inside constructor
}
}
class Program
{
static void Main()
{
var s = new Session("abc-123");
Console.WriteLine("Session: " + s.Id);
}
}readonly может использовать значения времени выполнения
В отличие от const, поле readonly может содержать значение, известное только во время работы программы, например сгенерированный идентификатор или текущее время.
using System;
class Order
{
public readonly Guid OrderId;
public Order()
{
OrderId = Guid.NewGuid();
}
}
class Program
{
static void Main()
{
var o = new Order();
Console.WriteLine("Has id: " + (o.OrderId != Guid.Empty));
}
}Статический readonly
Сочетайте static readonly, чтобы получить общее для класса значение, вычисляемое один раз во время выполнения. Обычно это замена const, когда значение не является литералом.
using System;
class AppInfo
{
public static readonly string[] Roles = { "admin", "user", "guest" };
}
class Program
{
static void Main()
{
Console.WriteLine("Roles: " + Roles());
}
static int Roles() => AppInfo.Roles.Length;
}Почему константы могут быть рискованными в разных сборках
Поскольку значения const встраиваются в вызывающий код во время компиляции, после изменения открытой константы в библиотеке необходимо перекомпилировать всех вызывающих её клиентов. static readonly позволяет этого избежать.
using System;
class Lib
{
public const int Version = 2; // inlined into callers
public static readonly int Build = 100; // read at runtime
}
class Program
{
static void Main()
{
Console.WriteLine(Lib.Version + "." + Lib.Build);
}
}Ни одно из них нельзя переназначить
После инициализации ни поле const, ни поле readonly нельзя изменить. Попытка сделать это приводит к ошибке компиляции.
using System;
class Demo
{
public const int A = 10;
public readonly int B;
public Demo() { B = 20; }
// A = 11; // would not compile
// B = 21; // would not compile outside constructor
}
class Program
{
static void Main()
{
var d = new Demo();
Console.WriteLine(Demo.A + ", " + d.B);
}
}Выбор между ними
Используйте const для настоящих литералов, которые никогда не меняются (число π, MaxInt). Используйте readonly, если значение вычисляется во время выполнения или может отличаться у разных экземпляров.
using System;
class Physics
{
public const double Gravity = 9.81; // universal literal
public readonly double Mass; // per object
public Physics(double mass) { Mass = mass; }
public double Weight() => Mass * Gravity;
}
class Program
{
static void Main()
{
var p = new Physics(10);
Console.WriteLine("Weight: " + p.Weight());
}
}Нюанс readonly-ссылки
readonly блокирует поле, но не объект, на который оно указывает. Ссылку на список, объявленную как readonly, нельзя переназначить, но её содержимое по-прежнему можно изменить.
using System;
using System.Collections.Generic;
class Cart
{
public readonly List<string> Items = new List<string>();
}
class Program
{
static void Main()
{
var c = new Cart();
c.Items.Add("Pen"); // allowed: mutating the object
c.Items.Add("Book");
Console.WriteLine("Items: " + c.Items.Count);
}
}Собираем всё вместе
В обычном классе const используют для фиксированных литералов, а readonly — для значений, фиксируемых отдельно для каждого экземпляра во время создания.
using System;
class Account
{
public const decimal MinBalance = 0m;
public readonly string Owner;
public Account(string owner)
{
Owner = owner;
}
}
class Program
{
static void Main()
{
var a = new Account("Rin");
Console.WriteLine(a.Owner + " min=" + Account.MinBalance);
}
}Быстрая проверка
Проверьте, насколько хорошо вы понимаете различия между const и readonly.
Итоги
const — это литерал времени компиляции, неявно статический и встраиваемый в вызывающий код. readonly задаётся один раз при объявлении или в конструкторе и может использовать значения времени выполнения. Используйте const для настоящих литералов, static readonly — для общих значений, вычисляемых во время выполнения, и помните: readonly блокирует ссылку, а не объект.
using System;
class Demo
{
public const int Max = 100;
public readonly int Created;
public Demo(int c) { Created = c; }
}
class Program
{
static void Main()
{
var d = new Demo(7);
Console.WriteLine(Demo.Max + ", " + d.Created);
}
}Часто задаваемые вопросы
Урок «Константы и поля readonly» бесплатный?
Да — полный текст урока «Константы и поля readonly» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Константы и поля readonly»?
Различайте const и static readonly. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Константы и поля readonly»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Статические методы и поля
- Статические классы для вспомогательных средств
- Константы и поля readonly
- Статические и экземплярные элементы