Превращаем строку в Enum в C#: гайд с примерами для гибкого кода

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

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

Начать курс

Как превратить строку в 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 с маленькой буквы? Нет,

Блоги

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