Как превратить строку в enum в C#: от новичка до профи
Каждый C#-разработчик рано или поздно сталкивается с ситуацией, когда нужно превратить обычную строку в перечисление (enum). Вы получаете данные из JSON, читаете настройки из конфигурационного файла или принимаете команду от пользователя — и вот перед вами строка, а код ждёт enum. Без правильной конвертации вы рискуете получить исключение или, что ещё хуже, незаметную ошибку в логике.
В этой статье мы разберём преобразование строки в enum в C# от простых методов до продвинутых техник. Вы узнаете, как безопасно парсить строки, обрабатывать ошибки и писать элегантный код. Материал основан на реальных вопросах с Stack Overflow — тема набрала тысячи просмотров не случайно.
Поехали!
Почему конвертация строки в enum — частая задача
Перечисления в C# — мощный инструмент для создания читаемого и типобезопасного кода. Но внешний мир обычно работает со строками: API возвращают "Admin", пользователь вводит "readonly", база данных хранит "Pending". Чтобы соединить эти миры, нужна конвертация string в enum C#.
Рассмотрим типовые сценарии:
- Десериализация JSON — поле статуса приходит как строка
- Парсинг аргументов командной строки
- Чтение настроек из appsettings.json
- Обработка пользовательского ввода в веб-формах
Без правильного подхода вы получите либо исключение, либо баги, которые трудно отловить. Давайте разберёмся с инструментарием.
Базовый метод: Enum.Parse — быстро и просто
Самый известный способ преобразовать строку в enum в C# — метод Enum.Parse. Он существует с первых версий .NET и до сих пор активно используется.
using System;
public enum UserRole
{
Admin,
Moderator,
User,
Guest
}
class Program
{
static void Main()
{
string input = "Admin";
UserRole role = (UserRole)Enum.Parse(typeof(UserRole), input);
Console.WriteLine(role); // Вывод: Admin
}
}
Здесь мы явно приводим результат к нужному типу, потому что Enum.Parse возвращает object. Метод чувствителен к регистру: строка "admin" вызовет исключение. Если вы не уверены в регистре, добавьте третий параметр:
UserRole role = (UserRole)Enum.Parse(typeof(UserRole), input, ignoreCase: true);
Теперь "admin", "ADMIN" и даже "AdMiN" будут корректно преобразованы. Но есть нюанс: если строка не соответствует ни одному значению enum, вы получите ArgumentException. А это значит — программа упадёт.
Когда Enum.Parse — плохой выбор
- Вы не контролируете входные данные (пользовательский ввод)
- Строка может быть null или пустой
- Вы хотите избежать исключений
Для таких случаев придумали Enum.TryParse.
Безопасный подход: Enum.TryParse — без исключений
Enum.TryParse в C# — ваш спасательный круг. Он не выбрасывает исключение, а возвращает bool: true, если конвертация успешна, и false в противном случае.
string input = "Moderator";
if (Enum.TryParse(input, ignoreCase: true, out UserRole result))
{
Console.WriteLine($"Роль: {result}");
}
else
{
Console.WriteLine("Не удалось распознать роль");
}
Обратите внимание: TryParse — generic-метод, поэтому не нужно приводить результат. Параметр ignoreCase работает так же, как в Parse. Этот метод идеален для безопасного парсинга enum C#.
Но есть подводный камень: TryParse считает успешным парсинг числовых строк. Строка "42" будет преобразована в значение enum с числовым эквивалентом 42, даже если такого значения нет. Чтобы избежать этого, добавьте проверку:
if (Enum.TryParse(input, ignoreCase: true, out UserRole result)
&& Enum.IsDefined(typeof(UserRole), result))
{
// Только настоящие имена enum
}
Теперь вы защищены от числовых "сюрпризов".
Работа с атрибутами: Enum.GetName и кастомные строки
Иногда строковые представления enum отличаются от имён полей. Например, в JSON статус может быть "in_progress", а в коде — InProgress. Тут на помощь приходят атрибуты.
using System.ComponentModel;
public enum OrderStatus
{
[Description("ожидание")]
Pending,
[Description("в_обработке")]
InProgress,
[Description("доставлен")]
Delivered
}
public static T GetEnumFromDescription<T>(string description) where T : Enum
{
foreach (var field in typeof(T).GetFields())
{
var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
as DescriptionAttribute;
if (attribute?.Description == description)
{
return (T)field.GetValue(null);
}
}
throw new ArgumentException($"Описание '{description}' не найдено в enum {typeof(T).Name}");
}
// Использование
string statusStr = "в_обработке";
OrderStatus status = GetEnumFromDescription<OrderStatus>(statusStr);
Console.WriteLine(status); // InProgress
Этот подход даёт полный контроль над преобразованием строки в enum C#, когда стандартные имена не подходят. Вы можете использовать любые атрибуты: DisplayAttribute, EnumMemberAttribute или даже собственные.
Продвинутые техники: Extension методы и LINQ
Чтобы код был чистым и переиспользуемым, оберните логику в extension-методы. Это стандартная практика для конвертации string в enum C# в реальных проектах.
public static class EnumExtensions
{
public static T ToEnum<T>(this string value, bool ignoreCase = true) where T : Enum
{
return (T)Enum.Parse(typeof(T), value, ignoreCase);
}
public static bool TryToEnum<T>(this string value, out T result, bool ignoreCase = true) where T : Enum
{
return Enum.TryParse(value, ignoreCase, out result);
}
}
// Использование
string input = "User";
UserRole role = input.ToEnum<UserRole>();
// или
if (input.TryToEnum<UserRole>(out var safeRole))
{
Console.WriteLine(safeRole);
}
С LINQ можно элегантно обработать список строк:
List<string> inputs = new() { "Admin", "guest", "Moderator", "Unknown" };
var roles = inputs
.Select(s => Enum.TryParse<UserRole>(s, ignoreCase: true, out var r) ? r : (UserRole?)null)
.Where(r => r.HasValue)
.Select(r => r.Value)
.ToList();
Console.WriteLine(string.Join(", ", roles)); // Admin, Moderator
Обратите внимание: "guest" не прошёл, потому что в нашем enum нет значения Guest с маленькой буквы? Нет,
Блоги
Рекомендаций по книгам
Читайте также
Интеграционное тестирование PHP с Docker: полное руководство
Swift-библиотеки, которые спасут ваш проект: гид по экосистеме
10 лучших фреймворков Swift для веб-разработки: продвинутый уровень
Обновляем значение в HashMap в Rust: от новичка до профи
CI/CD для TypeScript проектов: настройка GitHub Actions с нуля