Iterar sobre todos os valores de um enum é um requisito comum em C#. Você pode precisar preencher um menu suspenso, validar uma entrada ou executar uma ação para cada membro do enum. Este guia abrange todas as abordagens para iterar através de enums, incluindo auxiliares genéricos e tratamento de enums de flags.

Definindo um enum de exemplo

Todos os exemplos neste artigo utilizam o seguinte enum:

public enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

Método 1: Enum.GetValues com foreach

A abordagem mais comum usa Enum.GetValues, que retorna um Array com todos os valores definidos no enum:

foreach (Season season in Enum.GetValues(typeof(Season)))
{
    Console.WriteLine(season);
}

Saída:

Spring
Summer
Autumn
Winter

A conversão do Array retornado para Season é implícita quando você declara a variável do loop com o tipo do enum.

Método 2: Genérico Enum.GetValues (.NET 5+)

A partir do .NET 5, uma sobrecarga genérica está disponível que retorna um array fortemente tipado, eliminando a necessidade de typeof:

foreach (Season season in Enum.GetValues<Season>())
{
    Console.WriteLine(season);
}

Esta é a abordagem mais limpa para aplicações .NET modernas.

Método 3: Enum.GetNames

Se você precisa apenas dos nomes em string dos membros do enum, use Enum.GetNames:

foreach (string name in Enum.GetNames(typeof(Season)))
{
    Console.WriteLine(name);
}

Ou com a sobrecarga genérica (.NET 5+):

foreach (string name in Enum.GetNames<Season>())
{
    Console.WriteLine(name);
}

Isso retorna as mesmas strings que você obteria ao chamar .ToString() em cada valor do enum, mas sem a sobrecarga de boxing e unboxing.

Método 4: LINQ com valores de Enum

Você pode usar LINQ para filtrar, ordenar ou transformar valores de enum:

var warmSeasons = Enum.GetValues<Season>()
    .Where(s => s == Season.Spring || s == Season.Summer)
    .ToList();

foreach (var season in warmSeasons)
{
    Console.WriteLine(season);
}

Criando um dicionário a partir de um Enum

Um padrão comum é construir um dicionário que mapeia valores inteiros para nomes:

var seasonDict = Enum.GetValues<Season>()
    .ToDictionary(s => (int)s, s => s.ToString());

// {0: "Spring", 1: "Summer", 2: "Autumn", 3: "Winter"}

Método 5: Conversão para um array para acesso por índice

Se você precisa acessar valores do enum por índice:

Season[] seasons = (Season[])Enum.GetValues(typeof(Season));
Season third = seasons[2]; // Autumn
int count = seasons.Length; // 4

Ou com a versão genérica:

Season[] seasons = Enum.GetValues<Season>();

Preenchendo um menu suspenso a partir de um Enum

Um dos usos mais comuns no mundo real é preencher um controle de interface do usuário:

// Windows Forms ComboBox
comboBox.DataSource = Enum.GetValues<Season>();

// ASP.NET MVC SelectList
var items = Enum.GetValues<Season>()
    .Select(s => new SelectListItem
    {
        Value = ((int)s).ToString(),
        Text = s.ToString()
    })
    .ToList();

Analisando strings para valores de Enum

Para converter uma string em um valor de enum, use Enum.Parse ou Enum.TryParse:

// Throws ArgumentException if invalid
Season parsed = (Season)Enum.Parse(typeof(Season), "Summer");

// Safe parsing (returns false if invalid)
if (Enum.TryParse<Season>("Summer", out Season result))
{
    Console.WriteLine(result); // Summer
}

// Case-insensitive parsing
Enum.TryParse<Season>("summer", ignoreCase: true, out Season result2);

Conversão entre Enum e inteiro

// Enum to int
int value = (int)Season.Autumn; // 2

// Int to enum
Season season = (Season)2; // Autumn

// Check if value is defined
bool isDefined = Enum.IsDefined(typeof(Season), 2); // true
bool isUndefined = Enum.IsDefined(typeof(Season), 99); // false

Trabalhando com Enums de Flags

Enums de flags usam o atributo [Flags] e valores bit a bit, permitindo combinações:

[Flags]
public enum FilePermissions
{
    None    = 0,
    Read    = 1,
    Write   = 2,
    Execute = 4,
    All     = Read | Write | Execute
}

Iterando flags individuais

Enum.GetValues retorna todos os valores definidos, incluindo combinações como All. Para iterar apenas as flags individuais que estão definidas em um dado valor:

FilePermissions perms = FilePermissions.Read | FilePermissions.Write;

foreach (FilePermissions flag in Enum.GetValues<FilePermissions>())
{
    if (flag != FilePermissions.None && perms.HasFlag(flag))
    {
        Console.WriteLine(flag);
    }
}
// Output: Read, Write

Verificando flags individuais

FilePermissions perms = FilePermissions.Read | FilePermissions.Execute;

bool canRead = perms.HasFlag(FilePermissions.Read);       // true
bool canWrite = perms.HasFlag(FilePermissions.Write);     // false
bool canExecute = perms.HasFlag(FilePermissions.Execute); // true

Métodos auxiliares genéricos

Você pode criar métodos auxiliares reutilizáveis para operações com enums:

public static class EnumHelper
{
    /// <summary>
    /// Gets all values of an enum as a typed list.
    /// </summary>
    public static List<T> GetAllValues<T>() where T : struct, Enum
    {
        return Enum.GetValues<T>().ToList();
    }

    /// <summary>
    /// Gets a dictionary mapping enum names to values.
    /// </summary>
    public static Dictionary<string, T> GetNameValuePairs<T>() where T : struct, Enum
    {
        return Enum.GetValues<T>()
            .ToDictionary(e => e.ToString(), e => e);
    }

    /// <summary>
    /// Safely parses a string to an enum, returning a default value if parsing fails.
    /// </summary>
    public static T ParseOrDefault<T>(string value, T defaultValue = default)
        where T : struct, Enum
    {
        return Enum.TryParse<T>(value, ignoreCase: true, out T result)
            ? result
            : defaultValue;
    }
}

Uso:

List<Season> allSeasons = EnumHelper.GetAllValues<Season>();
Season parsed = EnumHelper.ParseOrDefault<Season>("summer", Season.Spring);

Referência rápida

TarefaMétodo
Iterar todos os valoresEnum.GetValues<T>()
Iterar todos os nomesEnum.GetNames<T>()
Analisar string para enumEnum.TryParse<T>(string, out T)
Enum para int(int)enumValue
Int para enum(T)intValue
Verificar se um valor é definidoEnum.IsDefined(typeof(T), value)
Verificar se uma flag está definidavalue.HasFlag(flag)

Resumo

A maneira mais simples de iterar através de um enum em C# é foreach (var value in Enum.GetValues<T>()) no .NET 5 e posterior, ou Enum.GetValues(typeof(T)) em frameworks mais antigos. Use Enum.GetNames quando precisar apenas dos nomes em string, e use o atributo [Flags] com HasFlag para combinações bit a bit de enums. Para código reutilizável, crie métodos auxiliares genéricos com a restrição where T : struct, Enum.