Как перебрать все значения Enum в C#: полный гайд с примерами

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

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

Начать курс

Как перебрать все значения Enum в C#: от новичка до профи

Представьте ситуацию: вы пишете игру на C#, и у вас есть перечисление Difficulty с уровнями сложности: Easy, Normal, Hard, Insane. Вам нужно вывести их все в меню выбора, или, скажем, создать выпадающий список для конфигуратора. Как это сделать? Руками писать массив строк? А если завтра добавится новый уровень? Придется лезть в код и менять его в трёх местах.

К счастью, в C# есть элегантное решение. Вопрос "How to loop through all enum values in C#?" — один из самых популярных на Stack Overflow (сотни тысяч просмотров). И сегодня мы разберем его полностью. Вы узнаете не один, а целых 4 способа перебора значений enum, поймете, какой когда использовать, и получите готовый код, который можно скопировать в свой проект.

Поехали!


Что такое Enum в C# и зачем его перебирать?

Enum (перечисление) — это набор именованных констант. Вместо того чтобы помнить, что 0 = Easy, 1 = Normal, 2 = Hard, вы пишете просто Difficulty.Easy. Код становится читаемым и безопасным.

Но когда в проекте 10-20 enum-значений, рано или поздно встает задача: получить их все. Например:

  • Заполнить ComboBox или Dropdown в UI.
  • Создать тестовые данные для всех вариантов.
  • Применить атрибуты к каждому значению.
  • Сравнить два enum-набора.

Вместо того чтобы писать:

string[] names = { "Easy", "Normal", "Hard", "Insane" };

…мы используем рефлексию и встроенные методы .NET. Это гибко, масштабируемо и не требует ручного обновления.


Способ 1: Классика — Enum.GetValues (самый популярный)

Это ответ, который вы найдете на Stack Overflow с наибольшим количеством голосов. Метод Enum.GetValues(typeof(YourEnum)) возвращает массив всех значений конкретного перечисления.

Пример кода:

using System;

public enum Difficulty
{
    Easy,
    Normal,
    Hard,
    Insane
}

class Program
{
    static void Main()
    {
        Console.WriteLine("Все уровни сложности:");
        
        // Получаем массив значений enum
        Difficulty[] allDifficulties = (Difficulty[])Enum.GetValues(typeof(Difficulty));
        
        foreach (Difficulty level in allDifficulties)
        {
            Console.WriteLine($"Уровень: {level} (числовое значение: {(int)level})");
        }
    }
}

Вывод в консоль:

Все уровни сложности:
Уровень: Easy (числовое значение: 0)
Уровень: Normal (числовое значение: 1)
Уровень: Hard (числовое значение: 2)
Уровень: Insane (числовое значение: 3)

Важно: Enum.GetValues возвращает массив типа Array, поэтому его нужно явно привести к вашему типу enum. Начиная с .NET 5, появилась дженерик-версия: Enum.GetValues<Difficulty>(), что чуть удобнее.

// .NET 5+ 
Difficulty[] allDifficulties = Enum.GetValues<Difficulty>();
foreach (var level in allDifficulties)
{
    Console.WriteLine(level);
}

Способ 2: Получаем имена через Enum.GetNames

Иногда вам нужны не сами значения, а их строковые имена (например, для UI). Для этого есть Enum.GetNames. Он возвращает массив строк.

Пример:

string[] names = Enum.GetNames(typeof(Difficulty));
Console.WriteLine("Названия уровней:");
foreach (string name in names)
{
    Console.WriteLine(name);
}

Вывод:

Названия уровней:
Easy
Normal
Hard
Insane

Когда использовать? Если вам нужны именно строки (например, для отображения в интерфейсе или логирования), а не сами enum-константы.


Способ 3: Linq и преобразование в List<T>

Современный C# и Linq позволяют сделать код еще лаконичнее. Особенно полезно, если вы хотите сразу получить список (List<Difficulty>) или выполнить дополнительные операции (фильтрацию, сортировку).

Пример:

using System;
using System.Linq;
using System.Collections.Generic;

// ...

// Преобразуем в List
List<Difficulty> difficultyList = Enum.GetValues(typeof(Difficulty))
                                       .Cast<Difficulty>()
                                       .ToList();

// Или еще проще (C# 7+)
List<Difficulty> difficultyList2 = Enum.GetValues<Difficulty>().ToList();

Console.WriteLine("Элементов в списке: " + difficultyList.Count);
difficultyList.ForEach(d => Console.WriteLine(d));

Продвинутый пример с фильтрацией: допустим, у вас есть enum с атрибутами, и вы хотите выбрать только те значения, у которых есть определенный атрибут [Description]. Linq отлично с этим справляется.

using System.ComponentModel;

public enum Difficulty
{
    [Description("Легко")]
    Easy,
    [Description("Нормально")]
    Normal,
    [Description("Сложно")]
    Hard,
    [Description("Безумие")]
    Insane
}

// Получаем только те значения, у которых Description не пустой
var withDescriptions = Enum.GetValues<Difficulty>()
                           .Where(d => 
                           {
                               var field = typeof(Difficulty).GetField(d.ToString());
                               return Attribute.IsDefined(field, typeof(DescriptionAttribute));
                           })
                           .ToList();

Способ 4: Использование Enum.GetValues с кастомными атрибутами

На реальных проектах enum часто содержит кастомные атрибуты — [Display], [Description], [EnumMember]. Чтобы эффективно перебирать такие значения, нужно читать атрибуты внутри цикла.

Полный пример с атрибутом Description:

using System;
using System.ComponentModel;
using System.Reflection;

public enum OperationStatus
{
    [Description("Операция выполнена успешно")]
    Success,
    [Description("Операция не удалась")]
    Failed,
    [Description("Операция в процессе")]
    Pending
}

class Program
{
    static void Main()
    {
        Console.WriteLine("Статусы операций и их описания:");
        
        foreach (OperationStatus status in Enum.GetValues<OperationStatus>())
        {
            // Получаем поле enum
            FieldInfo field = status.GetType().GetField(status.ToString());
            
            // Читаем атрибут Description
            DescriptionAttribute attribute = field.GetCustomAttribute<DescriptionAttribute>();
            string description = attribute != null ? attribute.Description : status.ToString();
            
            Console.WriteLine($"{status}: {description}");
        }
    }
}

Вывод:

Статусы операций и их описания:
Success: Операция выполнена успешно
Failed: Операция не удалась
Pending: Операция в процессе

Этот паттерн часто используется в ASP.NET Core для генерации выпадающих списков, в логировании

Блоги

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