Что такое enum (перечисление) в C#?

Ответ

enum (перечисление) в C# — это значимый тип данных (value type), который определяет набор именованных целочисленных констант. Он используется для создания типов с фиксированным набором допустимых значений, что делает код более читаемым и безопасным.

Базовый синтаксис и поведение:

// По умолчанию значения начинаются с 0 и увеличиваются на 1
enum Status
{
    Pending,    // 0
    Active,     // 1
    Inactive,   // 2
    Deleted     // 3
}

// Можно явно задавать значения
enum HttpStatusCode
{
    OK = 200,
    BadRequest = 400,
    NotFound = 404,
    InternalServerError = 500
}

// Использование
Status currentStatus = Status.Active;
Console.WriteLine(currentStatus); // Выведет: "Active"
Console.WriteLine((int)currentStatus); // Выведет: 1

Продвинутые возможности:

  1. Флаги (битовые перечисления): Используются, когда значения могут комбинироваться.

    [Flags]
    enum Permissions
    {
        None = 0,
        Read = 1,    // 2^0
        Write = 2,   // 2^1
        Execute = 4, // 2^2
        All = Read | Write | Execute // Комбинация
    }
    
    Permissions userPerms = Permissions.Read | Permissions.Write;
    Console.WriteLine(userPerms); // Выведет: "Read, Write"
    bool canWrite = userPerms.HasFlag(Permissions.Write); // true
  2. Базовый тип: По умолчанию int, но можно использовать другие целочисленные типы (byte, short, long и т.д.).

    enum SmallEnum : byte { Value1, Value2 }
  3. Преобразования:

    // Из строки в enum (с обработкой ошибок)
    if (Enum.TryParse<Status>("Active", out Status parsedStatus))
    {
        // Успешно
    }
    // Получение всех значений или имен
    var allValues = Enum.GetValues(typeof(Status));
    var allNames = Enum.GetNames(typeof(Status));

Практические рекомендации:

  • Используйте enum вместо "магических чисел" для повышения читаемости.
  • Для флагов всегда используйте атрибут [Flags] и задавайте значения степенями двойки.
  • Проверяйте допустимость значений при получении enum извне (например, из БД или API) с помощью Enum.IsDefined.
  • Рассмотрите использование switch выражения с enum для exhaustive checking (проверки на полноту покрытия всех случаев).

Ответ 18+ 🔞

Давай я тебе про enum в C# расскажу, как есть, без этих ваших заумных книжных формулировок. Представь, что тебе надоело писать в коде цифры, которые нихрена не понятны.

Вот смотри, пишешь ты статусы заказа:

int status = 1; // А че это за единица? Оплачен? Отправлен? Или курьер уже ебётся с твоей посылкой в подъезде?

А теперь с enum:

enum OrderStatus
{
    New = 0,       // Создан
    Paid = 1,      // Оплачен
    Shipped = 2,   // Отправлен
    Lost = 666     // Потерян, пиздец
}

OrderStatus status = OrderStatus.Paid;

Сразу видно, что заказ оплачен, а не гадаешь, что за хуйня такая — эта единица.

А теперь про флаги, это вообще песня. Допустим, у пользователя права. Он может читать, писать, удалять. Или всё сразу. Как хранить? В трёх булевых переменных? Не, так только конченый делает.

Делаем умно:

[Flags] // Этот атрибут говорит: "Эй, C#, тут битовые операции будут, не пугайся!"
enum UserPermissions
{
    None = 0,          // Вообще нихуя нельзя
    Read = 1,          // 0001 - Может смотреть
    Write = 2,         // 0010 - Может писать
    Delete = 4,        // 0100 - Может удалять
    All = Read | Write | Delete // 0111 - Может всё, царь и бог
}

// Даём пользователю право читать и писать
UserPermissions myPerms = UserPermissions.Read | UserPermissions.Write;

// Проверяем, может ли он удалять
if (myPerms.HasFlag(UserPermissions.Delete))
{
    Console.WriteLine("Может удалить всё к хуям!");
}
else
{
    Console.WriteLine("Не, удалять низя, только смотреть и портить.");
}

Важный момент — преобразования. Допустим, тебе из базы данных пришла строка "Active". Как её в enum превратить? Правильно — не тыкать наугад, а делать с проверкой:

if (Enum.TryParse<OrderStatus>("Lost", out var parsedStatus))
{
    // Всё ок, parsedStatus теперь OrderStatus.Lost
    Console.WriteLine($"Заказ {parsedStatus}, всё пропало!");
}
else
{
    // Прислали какую-то хуйню, которой нет в перечислении
    Console.WriteLine("Чё за статус такой? Не знаю я такого!");
}

И ещё одна фишка для параноиков. Получаешь ты значение откуда-то извне (API, чужой библиотеки, от коллеги-дауна). Всегда проверяй, а есть ли такое значение вообще в твоём enum:

int valueFromExternalShit = 999;
if (Enum.IsDefined(typeof(OrderStatus), valueFromExternalShit))
{
    // Всё норм, есть у нас такая константа
}
else
{
    // Нет такого, ёб твою мать! Кидаем исключение или обрабатываем как-то
    throw new ArgumentException("Какой-то левый статус пришёл, нахуй такое!");
}

Итог: enum — это офигенная штука, чтобы сделать код читаемым и не выёбываться с цифрами. Используй для статусов, кодов ошибок, наборов прав. Для флагов не забудь [Flags] и степени двойки. И всегда проверяй входящие значения, потому что мир жесток и полон мудаков, которые пришлют тебе что угодно.