Как преобразовать int в enum в C#? Приведение типов и Enum.Parse
Основные способы преобразования int в enum
В C# есть два основных подхода: явное приведение типа (cast) и использование Enum.Parse / Enum.TryParse. Выбор зависит от контекста: известно ли вам, что значение гарантированно существует в перечислении, или нужна проверка.
1. Явное приведение (cast) — простой и быстрый способ
Самый производительный метод — использовать явное приведение типа. Он подходит, когда вы уверены, что целое число соответствует одному из значений enum:
int statusValue = 2;
OrderStatus status = (OrderStatus)statusValue; // status == OrderStatus.Processing
Console.WriteLine(status); // Выведет: Processing
Важно: C# позволяет привести любое целое число к любому enum, даже если такого значения нет. Это не вызовет исключения — просто получится "некорректное" значение enum.
int invalidValue = 99;
OrderStatus badStatus = (OrderStatus)invalidValue; // Ошибки НЕТ!
Console.WriteLine(badStatus); // Выведет: 99 (число, а не имя)
Чтобы проверить, существует ли значение в enum, используйте метод Enum.IsDefined():
int value = 5;
if (Enum.IsDefined(typeof(OrderStatus), value))
{
OrderStatus status = (OrderStatus)value;
Console.WriteLine($"Статус: {status}");
}
else
{
Console.WriteLine($"Значение {value} не определено в перечислении");
}
2. Enum.Parse — для работы со строками
Если у вас строка (например, "2" или "Processing"), используйте Enum.Parse. Но для int он менее удобен, так как требует преобразования в строку:
string strValue = "2";
OrderStatus status = (OrderStatus)Enum.Parse(typeof(OrderStatus), strValue);
Обратите внимание: Enum.Parse выбросит ArgumentException, если строка не соответствует ни числу, ни имени элемента. Поэтому безопаснее использовать Enum.TryParse:
string input = "5";
if (Enum.TryParse<OrderStatus>(input, out OrderStatus result))
{
Console.WriteLine($"Успешно: {result}");
}
else
{
Console.WriteLine("Не удалось распарсить");
}
Но для преобразования из int в enum TryParse тоже работает, так как он принимает строковое представление числа:
int number = 3;
if (Enum.TryParse<OrderStatus>(number.ToString(), out OrderStatus status))
{
Console.WriteLine(status); // Shipped
}
3. Рекомендации по выбору
- Используйте явное приведение (cast), если вы на 100% уверены в корректности числа (например, значение получено из валидированного источника). Это самый быстрый способ.
- Добавьте проверку через
Enum.IsDefined, если есть риск получить некорректное значение. Это защитит от логических ошибок. - Используйте
Enum.TryParse, если работаете со строковыми данными (из конфигурации, пользовательского ввода, JSON).
4. Пример безопасного преобразования
public static OrderStatus SafeConvertToStatus(int value)
{
if (Enum.IsDefined(typeof(OrderStatus), value))
{
return (OrderStatus)value;
}
throw new ArgumentException($"Значение {value} не является допустимым статусом заказа");
}
// Использование:
try
{
OrderStatus status = SafeConvertToStatus(2);
Console.WriteLine(status); // Processing
}
catch (ArgumentException ex)
{
Console.WriteLine(ex.Message);
}
Этот подход сочетает производительность cast'а с защитой от невалидных данных.
<<Альтернативный подход: обобщённый метод-расширение
Для удобства можно создать универсальный метод-расширение, который будет работать с любым типом enum и автоматически проверять корректность значения:
public static class EnumExtensions
{
public static T ToEnum<T>(this int value) where T : Enum
{
if (Enum.IsDefined(typeof(T), value))
{
return (T)(object)value;
}
throw new ArgumentException($"Значение {value} не определено в перечислении {typeof(T).Name}");
}
}
// Использование:
int id = 3;
OrderStatus status = id.ToEnum<OrderStatus>();
Console.WriteLine(status); // Shipped
Плюсы этого подхода:
- Универсальность — работает для любых enum'ов.
- Читаемый синтаксис:
intValue.ToEnum<MyEnum>(). - Автоматическая проверка на валидность.
Минусы:
- Небольшое снижение производительности из-за boxing (упаковки в object).
- Требуется .NET Framework 4.5+ или .NET Core для ограничения
where T : Enum.
Если производительность критична (например, в цикле на миллион итераций), лучше использовать прямое приведение + Enum.IsDefined. Для обычного кода такой метод-расширение — отличное решение, повышающее читаемость и безопасность.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
Функции в Python: определение, вызов, параметры и return