Как получить int из enum в C#: от новичка до профи

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему enum без int — как кофе без кофеина?

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

Это не просто «хотелка» из учебника. По статистике Stack Overflow, вопрос «Get int value from enum in C#» собирает сотни тысяч просмотров. Даже опытные разработчики иногда путаются: кастинг? Convert.ToInt32? А что если тип базового целого числа — не int?

В этой статье мы разберём все легальные способы получить целочисленное значение из enum в C#. Начиная от простого приведения типов и заканчивая продвинутыми трюками с Unsafe.As (да, такое тоже есть!). Вы узнаете, какой метод быстрее, какой безопаснее, а какой лучше не использовать в продакшене.

1. Как устроен enum в C#: краткий ликбез

Прежде чем конвертировать, давайте вспомним матчасть. В C# enum — это тип-значение, который наследуется от System.Enum, а его базовый тип (underlying type) по умолчанию — int. Но вы можете явно указать другой тип:

public enum Status : byte
{
    New = 0,
    Active = 1,
    Closed = 2
}

public enum Priority : long
{
    Low = 10,
    Medium = 50,
    High = 100
}

Это важно! Если ваш enum использует byte или long, то простое приведение к int может привести к ошибке или потере данных.

2. Способ №1: явное приведение (cast) — классика жанра

Самый очевидный и быстрый способ — использовать оператор приведения типа. Работает, когда вы точно знаете, что базовый тип — int.

enum Day { Monday = 1, Tuesday = 2, Wednesday = 3 }

Day today = Day.Tuesday;
int dayValue = (int)today; // Результат: 2

Console.WriteLine(dayValue); // Выведет: 2

Плюсы:

  • Максимальная производительность — компилятор генерирует одну IL-инструкцию.
  • Простота и читаемость.

Минусы:

  • Если базовый тип не int, компилятор выдаст ошибку или предупреждение.
  • Не работает с enum, определёнными через long или byte (требуется двойной каст).

Когда использовать: в 90% случаев, когда ваш enum стандартный (: int).

3. Способ №2: Convert.ToInt32 — универсальный солдат

Метод Convert.ToInt32() — это швейцарский нож для конвертации. Он принимает object и пытается привести его к int через интерфейс IConvertible.

enum Status { New = 0, Active = 1, Closed = 2 }

Status current = Status.Active;
int statusCode = Convert.ToInt32(current); // Результат: 1

Console.WriteLine(statusCode); // 1

Плюсы:

  • Работает с любым базовым типом (byte, short, long и т.д.).
  • Не требует явного знания типа enum.

Минусы:

  • Медленнее, чем прямой каст (вызов виртуального метода).
  • Может выбросить InvalidCastException, если передать не enum.

Когда использовать: когда вы пишете обобщённый код или работаете с enum, базовый тип которого неизвестен на этапе компиляции.

4. Способ №3: GetHashCode() — опасный трюк (не делайте так!)

В интернете можно встретить «гениальный» совет: использовать GetHashCode(). Да, технически он вернёт целое число. Но это плохая практика.

enum Color { Red = 10, Green = 20, Blue = 30 }

Color c = Color.Green;
int hash = c.GetHashCode(); // Вернёт 20? Или нет?

Console.WriteLine(hash); // Скорее всего 20, но гарантий нет!

Почему это плохо? Документация Microsoft не гарантирует, что GetHashCode() вернёт именно значение enum. Это может быть результат хэш-функции, особенно для enum с long базовым типом.

Вердикт: никогда не используйте GetHashCode() для получения числового значения enum. Это баг, который вы будете искать неделями.

5. Способ №4: Работа с Enum.GetUnderlyingType — для гиков

Если вы пишете библиотеку или инструмент, который должен работать с любым enum, используйте рефлексию и Enum.GetUnderlyingType().

public static int EnumToInt(Enum value)
{
    // Получаем базовый тип
    Type underlyingType = Enum.GetUnderlyingType(value.GetType());
    
    // Конвертируем через Convert
    return Convert.ToInt32(Convert.ChangeType(value, underlyingType));
}

// Пример использования
enum Permission : byte { Read = 1, Write = 2, Execute = 4 }
Permission p = Permission.Write;
int result = EnumToInt(p); // Результат: 2

Плюсы:

  • Абсолютная универсальность — работает для byte, short, long.
  • Безопасность типов.

Минусы:

  • Медленно (рефлексия + двойная конвертация).
  • Избыточно для 99% задач.

6. Способ №5: unsafe и Unsafe.As — для экстремалов (C# 7.3+)

Если вам нужна максимальная производительность в критическом коде (игры, high-load сервисы), можно использовать System.Runtime.CompilerServices.Unsafe. Этот метод переинтерпретирует память enum как int без каких-либо проверок.

using System.Runtime.CompilerServices;

enum BigEnum : long
{
    Min = long.MinValue,
    Max = long.MaxValue
}

BigEnum val = BigEnum.Max;
long rawValue = Unsafe.As<BigEnum, long>(ref val); // Результат: 9223372036854775807

Console.WriteLine(rawValue);

Плюсы:

  • Максимальная скорость (н

Блоги

Рекомендаций по книгам