Есть ли в C# другой модификатор для констант?
Что проверяют
Знаете ли вы про readonly и понимаете ли разницу между константой времени компиляции и значением, которое фиксируется при выполнении. Следом почти всегда спрашивают, почему смена const в библиотеке может не доехать до потребителя.
Как отвечать
Да, это readonly, а как аналог константы на уровне типа static readonly. Разницу удобно разложить по пунктам:
- когда вычисляется: значение
constизвестно компилятору и вшивается прямо в IL вызывающего кода.readonlyприсваивается при выполнении, при объявлении или в конструкторе, аstatic readonlyв статическом конструкторе; - какие типы:
constбывает только у встроенных числовых типов,bool,char,string, перечислений иnullдля ссылочных.static readonlyподходит для чего угодно:TimeSpan.FromSeconds(30),Guid, массив, экземплярRegex; - статичность:
constнеявно статический, писатьstatic constнельзя.readonlyбезstaticхранится в каждом экземпляре и у разных объектов может отличаться; - где применимо: только
constгодится для метокcase, значений параметров по умолчанию и аргументов атрибутов. Затоconstможно объявить локально в методе, а локальныхreadonlyнет.
Правило выбора: const для того, что не меняется в принципе (число дней в неделе, математические константы), static readonly для настроек и публичных значений библиотеки. С C# 10 константой может быть и интерполированная строка из констант.
Где спотыкаются
Не знают о проблеме версий. Сборка A объявляет public const int MaxItems = 100, сборка B её использует. В A поменяли значение на 200, но B не пересобрали: в её IL по-прежнему 100. У static readonly такого эффекта нет, значение читается из A во время работы.
Думают, что readonly делает объект неизменяемым. readonly List<int> запрещает только присвоить полю другой список, а Add и Clear работают. Для неизменяемости нужны IReadOnlyList<T>, ImmutableArray<T> или FrozenSet<T>.
Выбирают const ради скорости. Разница со static readonly в современном .NET пренебрежимо мала, JIT после прогрева сам подставляет такие значения, а цена ошибки с версиями гораздо выше.