Что такое константа в C#?

Ответ

Константа (const) — это идентификатор, значение которого известно на этапе компиляции и не может быть изменено в течение всего времени жизни приложения.

Характеристики и синтаксис:

public const int MaxRetryCount = 3;
public const string ProductName = "MyApp";
public const double Pi = 3.14159;

Ключевые особенности const:

  1. Компиляция: Значение подставляется прямо в IL-код везде, где используется константа. Изменение константы требует перекомпиляции всех зависимых сборок.
  2. Типы данных: Могут быть только типами-значениями (int, double, bool, enum), string или null.
  3. Область видимости: Неявно являются static. Обращение: ClassName.ConstantName.
  4. Инициализация: Должны быть проинициализированы при объявлении.

Когда использовать const? Для истинно неизменяемых, фундаментальных значений, известных на этапе компиляции:

  • Математические константы (Math.PI — на самом деле static readonly, но концептуально).
  • Коды ошибок, магические числа.
  • Фиксированные строки-идентификаторы.

Альтернатива: readonly поле Используйте readonly, когда значение неизменно, но вычисляется в runtime (например, при создании объекта) или имеет недопустимый для const тип.

public class Config
{
    // Значение можно задать в конструкторе или инициализаторе
    public readonly DateTime StartupTime = DateTime.UtcNow;
    public readonly List<string> SupportedLanguages;

    public Config()
    {
        SupportedLanguages = LoadLanguages(); // runtime-инициализация
    }
}
Сравнение const vs readonly: Критерий const readonly
Время вычисления Компиляция Выполнение (runtime)
Типы данных Примитивы, string, enum Любые
Модификатор static Неявно статическая Может быть как статическим, так и экземплярным
Обновление значения Требует перекомпиляции всех клиентов Достаточно перекомпиляции только сборки, где объявлено поле

Ответ 18+ 🔞

А, константы, блядь! Ну это ж классика, хуле. Сидишь такой, пишешь код, и думаешь: "А не впендюрить ли мне сюда волшебное число 3?" А потом через полгода приходит коллега и спрашивает: "А это что за цифра 3, на которую всё завязано?" И ты такой: "Ну это... типа три попытки..." А он: "А почему не четыре?" И ты понимаешь, что ебал в рот этот магический номер, надо было константу делать.

Вот смотри, const — это как татуировка на жопе. На этапе компиляции её уже набили, и переписать "Люблю маму" на "Люблю папу" без боли и перекомпиляции всего, что на эту жопу смотрит, — нихуя не выйдет.

public const int MaxRetryCount = 3; // Всё, приехали. Тройка навеки.
public const string ProductName = "MyApp"; // Название, и ни шага в сторону.
public const double Pi = 3.14159; // Даже пи у нас своё, блядь, округлённое.

Чем эта штука характерна, а?

  1. Подстановка намертво: Компилятор берёт значение и вставляет его прямо в скомпилированный код, как засохшую жвачку под стол. Меняешь константу — всё, что от неё зависело, надо пересобирать заново, иначе будут смотреть на старое значение. Полный пиздец и разрушение доверия.
  2. Типы скудные: Только примитивы (int, bool), string или enum. Хочешь DateTime или List сделать константой? Иди на хуй, так не работает.
  3. Статика по умолчанию: Они неявно static. Обращаешься к ней как ClassName.ConstantName, а не через экземпляр. Логично же, раз значение одно на всех.
  4. Инициализация сразу: Объявил — тут же, блядь, присвой значение. Отложить на потом нельзя, runtime тебе не помощник.

Так когда её, блять, использовать-то? Да когда у тебя значение реально, нахуй, неизменное и известно прямо сейчас, когда ты код пишешь. Типа:

  • Математические константы (хотя Math.PI — это readonly, но суть ты понял).
  • Коды ошибок, которые в API прописаны.
  • Разные "магические числа", которые разбросаны по коду, чтобы их в одном месте собрать и назвать человечьим языком.

А если значение в runtime появляется? Тогда твой выход — readonly поле, друг мой. Это как временная татуха, которую можно нарисовать при создании объекта и потом уже не стирать.

public class Config
{
    // Время старта программы. На момент компиляции кто ж его знает?
    public readonly DateTime StartupTime = DateTime.UtcNow;
    // Список языков. Его из файла или базы подтягиваем, а не в коде хардкодим.
    public readonly List<string> SupportedLanguages;

    public Config()
    {
        SupportedLanguages = LoadLanguages(); // Вот тут, во время выполнения, инициализируем.
    }
}

Короче, краткая сводка, чтобы не ебать мозг:

Критерий const readonly
Когда значение известно При компиляции При выполнении (runtime)
Какие типы прокатят Примитивы, строки, енамы Любые, хоть HttpClient
Статика Да, всегда Может быть и статическим, и нет
Как обновить Пересобрать всё, что её использует Пересобрать только сборку, где поле объявлено

Вывод простой: если значение фундаментальное и менять его не планируется никогда — const. Если значение неизменное после создания, но вычисляется при работе программы или тип сложный — readonly. Не путай, а то будет тебе хиросима.