Как перебрать все значения перечисления (enum) в C#?
public enum Foos
{
A,
B,
C
}
Как правильно перебрать все возможные значения перечисления Foos в C#? Ищу решение, похожее на:
foreach(Foo in Foos)
но с правильным синтаксисом.
Для перебора всех значений перечисления (enum) в C# необходимо использовать метод Enum.GetValues или его универсальную версию Enum.GetValues<TEnum>, доступную начиная с .NET 5. Синтаксис, который вы ищете (foreach(Foo in Foos)), напрямую невозможен, но существует несколько эффективных подходов.
- Использование метода Enum.GetValues
- Использование универсального метода Enum.GetValues
- Использование Enum.GetNames для строковых имен
- Рекомендации по производительности
- Пример полного класса утилиты
Использование метода Enum.GetValues
Наиболее прямой подход - использование Enum.GetValues() в цикле foreach. Этот метод возвращает массив, содержащий все значения указанного типа перечисления.
public enum Foos
{
A,
B,
C
}
// Использование Enum.GetValues с foreach
foreach (Foos foo in Enum.GetValues(typeof(Foos)))
{
Console.WriteLine(foo);
}
// Вывод:
// A
// B
// C
Этот подход работает с любым типом перечисления, включая те, которые имеют пользовательские базовые значения или “пустоты” в их последовательности источник.
Использование универсального метода Enum.GetValues
Начиная с .NET 5, можно использовать универсальную версию, которая обеспечивает лучшую безопасность типов и избегает операций упаковки/распаковки:
// Подход для .NET 5+ - предпочтительный метод
var values = Enum.GetValues<Foos>();
foreach (Foos foo in values)
{
Console.WriteLine(foo);
}
// Или непосредственно в foreach
foreach (Foos foo in Enum.GetValues<Foos>())
{
Console.WriteLine(foo);
}
Универсальная версия более эффективна, так как не требует приведений типов или операций упаковки источник.
Использование Enum.GetNames для строковых имен
Если вам нужны только строковые имена значений перечисления без их целочисленных представлений, можно использовать Enum.GetNames():
// Получение только строковых имен
foreach (string name in Enum.GetNames(typeof(Foos)))
{
Console.WriteLine(name);
}
// Вывод:
// A
// B
// C
Этот метод возвращает массив строк, а не фактические значения перечисления источник.
Рекомендации по производительности
При выборе между методами учитывайте следующие характеристики производительности:
- Enum.GetValues
() (.NET 5+) - наиболее эффективный, избегает упаковки - Enum.GetValues(typeof(T)) - хорошая производительность, требует упаковки
- Enum.GetNames() - самый быстрый, если вам нужны только строки, но ограничен только именами
⚠️ Важно: Никогда не пытайтесь перебирать значения перечисления путем увеличения целых чисел, так как у перечислений могут быть “пустоты” в их значениях. Например, для перечисления
enum E { A = 1, B = 2, C = 4 }вы пропустите значение 3, если будете перебирать путем увеличения источник.
Пример полного класса утилиты
Для повторяющегося функционала перебора перечислений рассмотрите этот класс утилиты:
public static class EnumUtil
{
public static IEnumerable<T> GetValues<T>() where T : Enum
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
// Использование:
foreach (Foos foo in EnumUtil.GetValues<Foos>())
{
Console.WriteLine(foo);
}
}
Этот класс утилиты предоставляет чистый, повторно используемый способ перебора любого типа перечисления с надлежащей поддержкой универсальных типов источник.
Заключение
- Для проектов .NET 5+, используйте
Enum.GetValues<TEnum>()для наиболее эффективного и безопасного с точки зрения типов перебора - Для более старых версий .NET, используйте
Enum.GetValues(typeof(T))с соответствующим приведением типов - Когда вам нужны только строковые имена, используйте
Enum.GetNames(typeof(T)) - Избегайте увеличения целых чисел, так как это не позволит правильно обработать перечисления с пропусками или пользовательскими значениями
- Рассмотрите возможность создания класса утилиты, если вам часто требуется перебирать перечисления в вашем коде
Правильный способ перебрать все возможные значения вашего перечисления Foos - это либо:
foreach (Foos foo in Enum.GetValues<Foos>()) // .NET 5+
или
foreach (Foos foo in Enum.GetValues(typeof(Foos))) // Все версии
Источники
- Stack Overflow: How to loop through all enum values in C#?
- Microsoft Learn: Enum.GetValues Method
- Tutorial Teacher: How to loop through an enum in C#?
- Chris Pietschmann: C#: How to Enumerate over Enum values and names
- Net-Informations: How to loop through all enum values in C#
- Stack Overflow: Why is Enum.GetValues better than iterating?