Avatar ·

Как получить int значение из enum в C#? Преобразование перечисления в число

Всем привет! Я только начал изучать C# и столкнулся с проблемой. У меня есть перечисление (enum), которое описывает статусы заказа: ```csharp public enum OrderStatus { Created, Processing, Shipped, Delivered, Cancelled } ``` Мне нужно сохранить статус заказа в базу данных в виде целого числа (int). Например, `OrderStatus.Created` должно стать 0, `OrderStatus.Processing` — 1 и так далее. Но когда я пытаюсь просто присвоить значение: ```csharp int statusCode = OrderStatus.Created; ``` Компилятор выдаёт ошибку: "Cannot implicitly convert type 'OrderStatus' to 'int'". Я понимаю, что enum — это отдельный тип, а не просто число. Но как тогда правильно получить его числовое значение? Я пробовал делать `(int)OrderStatus.Created`, и это вроде работает, но я не уверен, что это правильный способ. Есть ли другие варианты? Может, есть какие-то подводные камни? Например, что если у меня enum с явно заданными значениями, как в примере ниже? ```csharp public enum HttpStatus { Ok = 200, NotFound = 404, InternalServerError = 500 } ``` Как в таком случае получить число? И можно ли сделать обратное преобразование — из int обратно в enum? Буду благодарен за подробное объяснение! <<>>

Прямое приведение (casting) — самый простой и правильный способ

Вы уже на правильном пути. Использование (int) для приведения enum к int — это стандартный и полностью корректный подход в C#. Дело в том, что любой enum в C# по умолчанию базируется на типе int (хотя можно использовать byte, short, long и другие целочисленные типы). Приведение просто говорит компилятору: "я знаю, что это число, воспринимай его как int".

public enum OrderStatus
{
    Created,      // 0
    Processing,   // 1
    Shipped,      // 2
    Delivered,    // 3
    Cancelled     // 4
}

// Получаем int значение
int statusCode = (int)OrderStatus.Shipped;  // statusCode = 2
Console.WriteLine(statusCode);  // Выведет: 2

Для enum с явными значениями всё работает точно так же:

public enum HttpStatus
{
    Ok = 200,
    NotFound = 404,
    InternalServerError = 500
}

int code = (int)HttpStatus.NotFound;  // code = 404

Обратное преобразование: из int в enum

Чтобы преобразовать число обратно в enum, также используется приведение:

int statusCodeFromDb = 3;
OrderStatus status = (OrderStatus)statusCodeFromDb;  // status = OrderStatus.Delivered

// Для HttpStatus:
int httpCode = 404;
HttpStatus status = (HttpStatus)httpCode;  // status = HttpStatus.NotFound

Важные нюансы и подводные камни

  • Невалидные значения: Если вы передадите число, которого нет в enum, приведение всё равно сработает без ошибки — это может привести к неожиданным багам. Всегда проверяйте с помощью Enum.IsDefined():
int unknownCode = 999;
if (Enum.IsDefined(typeof(OrderStatus), unknownCode))
{
    OrderStatus status = (OrderStatus)unknownCode;
}
else
{
    // Обработка ошибки
    Console.WriteLine("Неизвестный статус");
}
  • Enum с другим базовым типом: Если ваш enum объявлен как enum Foo : byte, то приведение к int всё равно работает, но нужно быть осторожным с диапазоном значений.
  • Производительность: Приведение — это очень быстрая операция, практически без накладных расходов.

Альтернативные методы (менее предпочтительные)

Хотя приведение — лучший способ, есть и другие варианты, которые вы можете встретить в коде:

// Convert.ToInt32() — работает, но избыточно
int val1 = Convert.ToInt32(OrderStatus.Processing);

// GetHashCode() — НЕ ИСПОЛЬЗУЙТЕ! Это не то, что вам нужно
int val2 = OrderStatus.Processing.GetHashCode(); // Опасно!

Важно: Метод GetHashCode() для enum возвращает то же значение, что и приведение, но полагаться на это — плохая практика. В будущих версиях .NET это может измениться.

Современные подходы (C# 7.3+ и .NET Core 3.0+)

Если вы используете современные версии C#, можно воспользоваться generic-методами из пространства имен System.Enum:

// Более типобезопасный способ (требует .NET 5+)
int val = Enum.Parse<OrderStatus>("Shipped"); // Но это для строк, не для чисел

// Для преобразования в int лучше всё равно использовать приведение

Рекомендация для работы с БД

При сохранении enum в базу данных (например, через Entity Framework) часто используют конфигурацию, которая автоматически хранит enum как int. Но если вы работаете напрямую с ADO.NET или Dapper, приведение — ваш выбор:

// Сохранение
int statusInt = (int)order.Status;
command.Parameters.AddWithValue("@Status", statusInt);

// Чтение
int statusFromDb = (int)reader["Status"];
OrderStatus status = (OrderStatus)statusFromDb;

В итоге: используйте простое приведение (int) — это идиоматичный, быстрый и понятный способ. Добавляйте проверку Enum.IsDefined() для защиты от невалидных значений, если данные приходят из ненадёжного источника.

<<>>

Альтернативный подход: использование System.Enum и конвертеров

Помимо прямого приведения, в некоторых случаях удобно использовать универсальные методы. Например, если вы работаете с generic-кодом или не знаете тип enum на этапе компиляции:

public static int EnumToInt<T>(T enumValue) where T : Enum
{
    return Convert.ToInt32(enumValue);
}

// Использование:
int code = EnumToInt(HttpStatus.Ok); // code = 200

Этот подход полезен, когда нужно написать общий метод для работы с любыми enum. Однако он медленнее прямого приведения из-за boxing'а (упаковки значения в object).

Безопасное преобразование с TryParse

Для обратного преобразования из int в enum можно использовать Enum.TryParse, который сразу проверяет валидность:

int value = 200;
if (Enum.TryParse<HttpStatus>(value.ToString(), out HttpStatus result))
{
    // result = HttpStatus.Ok
}
else
{
    Console.WriteLine("Невалидное значение");
}

Недостаток: этот метод работает со строками, поэтому нужно делать .ToString(), что неэффективно. Для чисел лучше использовать приведение + Enum.IsDefined.

Когда использовать альтернативы?

  • Если вы пишете библиотеку или утилиту для работы с произвольными enum — generic-метод с Convert.
  • Если данные приходят из внешнего источника и могут быть некорректными — комбинация приведения + IsDefined.
  • Во всех остальных случаях — простое приведение (int).

Также стоит отметить, что в .NET 7+ появился метод Enum.ToObject, который тоже может быть использован, но он менее удобен, чем прямое приведение.