Como enumerar uma enumeração

3767

Como você pode enumerar um enumem c #?

Por exemplo, o seguinte código não compila:

public enum Suit
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod()
{
    foreach (Suit suit in Suit)
    {
        DoSomething(suit);
    }
}

E fornece o seguinte erro em tempo de compilação:

'Suit' é um 'tipo', mas é usado como uma 'variável'

Falha na Suitpalavra - chave, a segunda.

Ian Boyd
fonte
17
Veja também ... stackoverflow.com/questions/972307/…
SteveC 04/08/09
2
Você pode querer verificar os prós e contras de C enums # , que discute este, bem como outros petiscos enum útil
ChaseMedallion

Respostas:

4613
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

Nota : A conversão para (Suit[])não é estritamente necessária, mas torna o código 0,5 ns mais rápido .

piada
fonte
97
Isso não funciona se você tiver valores duplicados na lista de enumeradores.
Jessy
10
Eu só quero ressaltar que isso, infelizmente, não funcionará no silverlight, pois a biblioteca do silverlight não é composta enum.GetValues. Você precisa usar a reflexão neste caso.
Giacomo Tagliabue
146
@Jessy este faz o trabalho em caso de situações duplicados como enum E {A = 0, B = 0}. Enum.GetValuesresulta em dois valores sendo retornados, embora sejam os mesmos. E.A == E.Bé verdade, então não há distinção. Se você quiser nomes individuais, deve procurar Enum.GetNames.
Nawfal # 7/13
13
Se você possui duplicatas / sinônimos na sua enumeração e deseja outro comportamento, pode usar a Distinctextensão do Linq (desde o .NET 3.5) foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Jeppe Stig Nielsen
42
Eu cometi o erro de tentar usar varpara o tipo. O compilador tornará a variável um em Objectvez da enumeração. Liste o tipo de enum explicitamente.
Jpmc26
695

Parece-me que você realmente deseja imprimir os nomes de cada enumeração, e não os valores. Nesse caso, Enum.GetNames()parece ser a abordagem correta.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (string name in Enum.GetNames(typeof(Suits)))
    {
        System.Console.WriteLine(name);
    }
}

A propósito, incrementar o valor não é uma boa maneira de enumerar os valores de uma enumeração. Você deve fazer isso.

Eu usaria em seu Enum.GetValues(typeof(Suit))lugar.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}
Haacked
fonte
2
Sintaxe do VB aqui: link
AndruWitta
Tomei a sua versão com uma pequena sequência de alterações do meu lado: Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). Nesse caso, eu posso iterar a matriz de Suitsitens de enumeração, não seqüências de caracteres.
Barabas
@Barabas porque não basta fazer Suits suit in Enum.GetValues(typeof(Suits))?
themadking
@themadking oh, cara! é claro, usar o tipo exato parece melhor do que esse pedaço monstruoso de sh ... código!
Barabas
337

Fiz algumas extensões para facilitar o uso de enum. Talvez alguém possa usá-lo ...

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all items for an enum type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>() where T : struct
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all combined items from an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    /// <example>
    /// Displays ValueA and ValueB.
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
    /// {
    ///    Console.WriteLine(item);
    /// }
    /// </code>
    /// </example>
    public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        foreach (object item in Enum.GetValues(typeof(T)))
        {
            int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            if (itemAsInt == (valueAsInt & itemAsInt))
            {
                yield return (T)item;
            }
        }
    }

    /// <summary>
    /// Determines whether the enum value contains a specific value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="request">The request.</param>
    /// <returns>
    ///     <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
    /// </returns>
    /// <example>
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
    /// {
    ///     Console.WriteLine("dummy contains EnumExample.ValueA");
    /// }
    /// </code>
    /// </example>
    public static bool Contains<T>(this Enum value, T request)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
        int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);

        if (requestAsInt == (valueAsInt & requestAsInt))
        {
            return true;
        }

        return false;
    }
}

A enum em si deve ser decorada com o FlagsAttribute :

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
prumo
fonte
13
Um revestimento para o primeiro método de extensão; não é mais preguiçoso. return Enum.GetValues ​​(typeof (T)). Cast <T> ();
Leyu
2
Como alternativa, você também pode usar o OfType: Enum.GetValues ​​(typeof (T)). OfType <T> (). É uma pena que não haja uma versão genérica de GetValues ​​<T> (), então seria ainda mais eficiente.
precisa saber é o seguinte
3
Talvez alguém possa mostrar como usar essas extensões? O compilador não mostra métodos de extensão na enumeração EnumExample.
Tomas
1
alguém pode adicionar um exemplo de como utilizar essas funções?
Ashwini Verma
3
+1 para código reutilizável: exemplos - salve esses métodos de extensão em uma biblioteca e faça referência a ele [Flags] enum public mytypes {name1, name2}; List <string> myTypeNames = mytypes.GetAllItems ();
22413 Krishna
178

Algumas versões da estrutura .NET não suportam Enum.GetValues. Aqui está uma boa solução alternativa do Ideas 2.0: Enum.GetValues ​​no Compact Framework :

public Enum[] GetValues(Enum enumeration)
{
    FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
    Enum[] enumerations = new Enum[fields.Length];

    for (var i = 0; i < fields.Length; i++)
        enumerations[i] = (Enum) fields[i].GetValue(enumeration);

    return enumerations;
}

Como em qualquer código que envolve reflexão , você deve executar etapas para garantir que seja executado apenas uma vez e que os resultados sejam armazenados em cache.

Ekevoo
fonte
18
Por que não usar a palavra-chave yield aqui em vez de instanciar uma lista?
Eric Mickelsen
1
ou mais curto:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
nawfal 7/11/13
7
@nawfal: Linq não está disponível .Net CF 2.0.
Gabriel GM
@Ekevoo Como vincular esses valores de enum a um DropDownList no MVC?
Jack
115

Use Cast<T>:

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

Lá vai você IEnumerable<Suit>.

sircodesalot
fonte
1
Isso também funciona na fromcláusula e no foreachdeclarador do cabeçalho.
Aluan Haddad
97

Eu acho que isso é mais eficiente do que outras sugestões, porque GetValues()não é chamado toda vez que você tem um loop. Também é mais conciso. E você recebe um erro em tempo de compilação, não uma exceção de tempo de execução, se Suitnão for um enum.

EnumLoop<Suit>.ForEach((suit) => {
    DoSomethingWith(suit);
});

EnumLoop tem esta definição completamente genérica:

class EnumLoop<Key> where Key : struct, IConvertible {
    static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
    static internal void ForEach(Action<Key> act) {
        for (int i = 0; i < arr.Length; i++) {
            act(arr[i]);
        }
    }
}
James
fonte
6
Cuidado ao usar genéricos como este. Se você tentar usar EnumLoopcom algum tipo que não seja enum, ele será compilado corretamente, mas lançará uma exceção no tempo de execução.
svick
7
Obrigado svick. Na verdade, as exceções de tempo de execução ocorrerão com as outras respostas nesta página ... exceto esta porque eu adicionei "where Key: struct, IConvertible" para que você obtenha um erro de tempo de compilação na maioria dos casos.
James
3
Não, GetValues ​​() é chamado apenas uma vez no foreach.
Alex Blokha
4
James, eu desencorajaria sua classe porque é inteligente escrever, mas no código de produção que muitas pessoas manterão e atualizarão, é um trabalho extra. Se fizer uma grande economia ou for muito usada - a economia é grande e as pessoas se familiarizam com ela - vale a pena, mas na maioria dos casos diminui a velocidade das pessoas que tentam ler e atualizar o código e introduz uma possível erros de origem no futuro. Menos código é melhor :) menos complexidade é ainda melhor.
Grant M
2
@GrantM Por quê? Esse código não é complexo e é incrivelmente curto. Além disso, escrever a classe uma vez permitirá iterações de código ainda mais curtas com o uso, conforme seu exemplo. Isso é extremamente limpo, se você não pode atualizar esse código, provavelmente não pode atualizar nenhum código da empresa.
Dispersia
77

Você não entra Enum.GetValues()no Silverlight .

Postagem original do blog de Einar Ingebrigtsen :

public class EnumHelper
{
    public static T[] GetValues<T>()
    {
        Type enumType = typeof(T);

        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<T> values = new List<T>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add((T)value);
        }

        return values.ToArray();
    }

    public static object[] GetValues(Type enumType)
    {
        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<object> values = new List<object>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add(value);
        }

        return values.ToArray();
    }
}
Aubrey Taylor
fonte
2
Solução agradável, mas alguma refatoração será melhor! :)
Nawfal
Eu estou usando o .NET Framework 4.0 e Enum.GetValues Silverlight trabalho, o código que usei é ---> Enum.GetValues (typeof (enum))
Ananda
2
Começando com C # 7.3 (Visual Studio 2017 ≥ v15.7), pode-se usar o #where T: Enum
Yahoo Serious
59

Minha solução funciona no .NET Compact Framework (3.5) e oferece suporte à verificação de tipo em tempo de compilação :

public static List<T> GetEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> GetEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}
  • Se alguém souber como se livrar do T valueType = new T(), ficaria feliz em ver uma solução.

Uma chamada ficaria assim:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
Mallox
fonte
2
que tal usar T valueType = default(T)?
7117 Oliver
Ótimo, eu nem conhecia essa palavra-chave. Sempre bom aprender algo novo. Obrigado! Ele sempre retorna uma referência ao mesmo objeto ou cria uma nova instância sempre que a instrução padrão é chamada? Eu não encontrei nada na rede sobre isso até agora, mas se ele cria uma nova instância toda vez, meio que derrota o objetivo que eu estava procurando (ter uma linha ^^).
Mallox 08/07/10
1
Isso não criaria uma nova instância para cada iteração na enumeração?
Mallox
1
-1 para "suporta verificação de tipo em tempo de compilação:". Que tipo de verificação? Isso funcionaria para qualquer um new() T. Além disso, você não precisa new T(), você pode selecionar apenas os campos estáticos sozinho e fazer .GetValue(null). Veja a resposta de Aubrey.
Nawfal
2
Começando com C # 7.3 (Visual Studio 2017 ≥ v15.7), pode-se usar o #where T: Enum
Yahoo Serious
52

Eu acho que você pode usar

Enum.GetNames(Suit)
Tom Carr
fonte
6
Enum.GetValues ​​(Ternos)
Ian Boyd
50
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
Joshua Drake
fonte
2
Isso enumera uma string, não se esqueça de converter essas coisas novamente em um valor de enumeração para que a enumeração possa ser enumerada.
Ian Boyd
1
Vejo pela sua edição que você deseja realmente operar nas enums, o código acima abordou sua postagem original.
Joshua Drake
49
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

Ouvi rumores vagos de que isso é terrivelmente lento. Ninguem sabe? - Orion Edwards 15/10/08 às 1:31 7

Eu acho que o cache da matriz aceleraria consideravelmente. Parece que você está obtendo uma nova matriz (através da reflexão) sempre. Em vez:

Array enums = Enum.GetValues(typeof(Suit));
foreach (Suit suitEnum in enums) 
{
    DoSomething(suitEnum);
}

Isso é pelo menos um pouco mais rápido, ja?

Expiação limitada
fonte
5
O compilador deve cuidar disso, no entanto.
Stephan Bijzitter 23/02
@StephanBijzitter Uau, você está lendo muito abaixo :-) Eu concordo, o compilador deve tornar minha solução desnecessária.
Expiação limitada
1
Isso não é necessário. Observando o código compilado no ILSpy, o compilador definitivamente já faz isso. Por que essa resposta é votada, muito menos 35 vezes?
Mshry1384 #
1
Foi votado há muito tempo. A muito tempo atras. Eu apostaria que o compilador também teria resolvido isso naquela época. Mas com certeza parece mais eficiente, não é? ;-)
Expiação limitada
32

Três caminhos:

  1. Enum.GetValues(type) // Desde o .NET 1.1, não no Silverlight ou no .NET Compact Framework
  2. type.GetEnumValues() // Somente no .NET 4 e acima
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Funciona em qualquer lugar

Não sei por que GetEnumValuesfoi introduzido nas instâncias de tipo. Não é muito legível para mim.


Ter uma classe auxiliar como Enum<T>é o mais legível e memorável para mim:

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<T> GetValues()
    {
        return (T[])Enum.GetValues(typeof(T));
    }

    public static IEnumerable<string> GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
}

Agora você liga para:

Enum<Suit>.GetValues();

// Or
Enum.GetValues(typeof(Suit)); // Pretty consistent style

Também é possível usar algum tipo de cache se o desempenho for importante, mas não espero que isso seja um problema.

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    // Lazily loaded
    static T[] values;
    static string[] names;

    public static IEnumerable<T> GetValues()
    {
        return values ?? (values = (T[])Enum.GetValues(typeof(T)));
    }

    public static IEnumerable<string> GetNames()
    {
        return names ?? (names = Enum.GetNames(typeof(T)));
    }
}
nawfal
fonte
Este é um bom resumo de métodos. Eu acho que você deve mesclar sua outra resposta nisso. A verdade é que a enumeração é especial e o looping é frequentemente (geralmente) tão válido quanto a enumeração, porque você sabe que os valores nunca serão alterados. IOW, se você tem uma enumeração que muda o tempo todo, escolheu a construção de dados incorreta para começar.
krowe2
31

Apenas combinando as respostas principais, juntei uma extensão muito simples:

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this T value) where T : Enum
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

É limpo, simples e, pelo comentário de @ Jeppe-Stig-Nielsen, rápido.

Lado escuro
fonte
6
Começando com C # 7.3 (Visual Studio 2017 ≥ v15.7), pode-se usar o #where T: Enum
Yahoo Serious
24

Existem duas maneiras de iterar um Enum:

1. var values =  Enum.GetValues(typeof(myenum))
2. var values =  Enum.GetNames(typeof(myenum))

O primeiro fornecerá valores em forma em uma matriz de ** object** s, e o segundo fornecerá valores em forma de uma matriz de **String ** s.

Use-o em um foreachloop como abaixo:

foreach(var value in values)
{
    // Do operations here
}
Kylo Ren
fonte
2
Talvez porque isso já esteja coberto em muitas respostas? Não vamos tornar as respostas redundantes.
Nawfal 17/05
@nawfal yes pode ser abordado em outras respostas, embora não tenha sido concluído bem na maioria delas.
Kylo Ren
23

Eu uso ToString (), em seguida, dividir e analisar a matriz cuspir em sinalizadores.

[Flags]
public enum ABC {
   a = 1,
   b = 2,
   c = 4
};

public IEnumerable<ABC> Getselected (ABC flags)
{
   var values = flags.ToString().Split(',');
   var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));
   return enums;
}

ABC temp= ABC.a | ABC.b;
var list = getSelected (temp);
foreach (var item in list)
{
   Console.WriteLine(item.ToString() + " ID=" + (int)item);
}
Mickey Perlstein
fonte
17

Não acredito que isso seja melhor ou até bom. Estou apenas afirmando mais uma solução.

Se os valores de enum variam estritamente de 0 a n - 1, uma alternativa genérica é:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

Se os valores da enumeração forem contíguos e você puder fornecer o primeiro e o último elemento da enumeração, então:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

Mas isso não é estritamente enumerado, apenas repetido. O segundo método é muito mais rápido do que qualquer outra abordagem ...

nawfal
fonte
16

Se você precisar de verificação de velocidade e tipo no tempo de compilação e execução, esse método auxiliar é melhor do que usar o LINQ para converter cada elemento:

public static T[] GetEnumValues<T>() where T : struct, IComparable, IFormattable, IConvertible
{
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException(string.Format("{0} is not of type System.Enum", typeof(T)));
    }
    return Enum.GetValues(typeof(T)) as T[];
}

E você pode usá-lo como abaixo:

static readonly YourEnum[] _values = GetEnumValues<YourEnum>();

Claro que você pode voltar IEnumerable<T>, mas isso não lhe comprará nada aqui.

dmihailescu
fonte
3
Começando com C # 7.3 (Visual Studio 2017 ≥ v15.7), pode-se usar o #where T: Enum
Yahoo Serious
14

Aqui está um exemplo prático de criação de opções de seleção para uma DDL :

var resman = ViewModelResources.TimeFrame.ResourceManager;

ViewBag.TimeFrames = from MapOverlayTimeFrames timeFrame
      in Enum.GetValues(typeof(MapOverlayTimeFrames))
      select new SelectListItem
      {
         Value = timeFrame.ToString(),
         Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()
      };
jhilden
fonte
10
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(A resposta atual aceita tem um elenco que eu acho que não é necessário (embora eu possa estar errado).)

queimaduras mate
fonte
10

Esta pergunta aparece no capítulo 10 do " C # Step by Step 2013 "

O autor usa um loop for duplo para iterar através de um par de enumeradores (para criar um baralho completo de cartas):

class Pack
{
    public const int NumSuits = 4;
    public const int CardsPerSuit = 13;
    private PlayingCard[,] cardPack;

    public Pack()
    {
        this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];
        for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++)
        {
            for (Value value = Value.Two; value <= Value.Ace; value++)
            {
                cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);
            }
        }
    }
}

Nesse caso, Suite Valuesão ambas as enumerações:

enum Suit { Clubs, Diamonds, Hearts, Spades }
enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

e PlayingCardé um objeto de cartão com um definido Suite Value:

class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}
Ross Gatih
fonte
isso funcionará se os valores em enum não forem seqüenciais?
Aamir Masood #
10

Eu sei que é um pouco bagunçado, mas se você é fã de one-liners, aqui está um:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
anar khalilov
fonte
2
Isso é cegueira ?
Mikael Dúi Bolinder 01/03/19
8

E se você souber que o tipo será um enum, mas não souber qual é o tipo exato no momento da compilação?

public class EnumHelper
{
    public static IEnumerable<T> GetValues<T>()
    {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }

    public static IEnumerable getListOfEnum(Type type)
    {
        MethodInfo getValuesMethod = typeof(EnumHelper).GetMethod("GetValues").MakeGenericMethod(type);
        return (IEnumerable)getValuesMethod.Invoke(null, null);
    }
}

O método getListOfEnumusa reflexão para obter qualquer tipo de enumeração e retorna um IEnumerablede todos os valores de enumeração.

Uso:

Type myType = someEnumValue.GetType();

IEnumerable resultEnumerable = getListOfEnum(myType);

foreach (var item in resultEnumerable)
{
    Console.WriteLine(String.Format("Item: {0} Value: {1}",item.ToString(),(int)item));
}
Slappywag
fonte
8

Uma maneira simples e genérica de converter uma enumeração em algo que você pode interagir:

public static Dictionary<int, string> ToList<T>() where T : struct
{
   return ((IEnumerable<T>)Enum
       .GetValues(typeof(T)))
       .ToDictionary(
           item => Convert.ToInt32(item),
           item => item.ToString());
}

E depois:

var enums = EnumHelper.ToList<MyEnum>();
Gabriel
fonte
A Dictionarynão é uma boa ideia: se você Enumgosta enum E { A = 0, B = 0 }, o valor 0 é adicionado 2 vezes, gerando um ArgumentException(você não pode adicionar o mesmo Keyem Dictionary2 ou mais vezes!).
Massimiliano Kraus
Por que retornar a Dictionary<,>partir de um método chamado ToList? Também porque não voltar Dictionary<T, string>?
Aluan Haddad
8

Adicione método public static IEnumerable<T> GetValues<T>()à sua classe, como:

public static IEnumerable<T> GetValues<T>()
{
    return Enum.GetValues(typeof(T)).Cast<T>();
}

Ligue e passe seu enum. Agora você pode iterar usando foreach:

 public static void EnumerateAllSuitsDemoMethod()
 {
     // Custom method
     var foos = GetValues<Suit>();
     foreach (var foo in foos)
     {
         // Do something
     }
 }
MUT
fonte
2

enumOs tipos são chamados de "tipos de enumeração" não porque são contêineres que "enumeram" valores (que não são), mas porque são definidos pela enumeração dos valores possíveis para uma variável desse tipo.

(Na verdade, isso é um pouco mais complicado do que isso - os tipos de enum são considerados como tendo um tipo inteiro "subjacente", o que significa que cada valor de enum corresponde a um valor inteiro (isso geralmente é implícito, mas pode ser especificado manualmente). de uma maneira que você possa encher qualquer inserir número inteiro desse tipo na variável enum, mesmo que não seja um valor "nomeado".)

O método System.Enum.GetNames pode ser usado para recuperar uma matriz de seqüências de caracteres que são os nomes dos valores de enumeração, como o nome sugere.

Edição: deveria ter sugerido o método System.Enum.GetValues . Opa

Emily Chen
fonte
2
Embora sua resposta seja correta em si mesma, ela realmente não aborda a pergunta original do OP. O GetNamesmétodo retorna, de fato, uma matriz de cadeias de caracteres, mas o OP requer um enumerador através dos valores.
Silviu Preda
@SilviuPreda: Editado. Deveria ter sido GetValues ​​em vez de GetNames.
Emily Chen
2

Eu tentei de várias maneiras e obtive o resultado deste código:

Para obter uma lista de int de uma enumeração, use o seguinte. Funciona!

List<int> listEnumValues = new List<int>();
YourEnumType[] myEnumMembers = (YourEnumType[])Enum.GetValues(typeof(YourEnumType));
foreach ( YourEnumType enumMember in myEnumMembers)
{
    listEnumValues.Add(enumMember.GetHashCode());
}
reza akhlaghi
fonte
1
tanx para edit @ peter-mortensen
reza akhlaghi 11/11/19
0

Também é possível vincular diretamente aos membros estáticos públicos da enum usando reflexão:

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
    .ToList().ForEach(x => DoSomething(x.Name));
Termininja
fonte
0

Se você tem:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Este:

foreach (var e in Enum.GetValues(typeof(Suit)))
{
    Console.WriteLine(e.ToString() + " = " + (int)e);
}

Saída:

Spades = 0
Hearts = 1
Clubs = 2
Diamonds = 3
rlv-dan
fonte
0

Maneira genérica de LINQ :

    public static Dictionary<int, string> ToList<T>() where T : struct =>
        ((IEnumerable<T>)Enum.GetValues(typeof(T))).ToDictionary(value => Convert.ToInt32(value), value => value.ToString());

Uso:

        var enums = ToList<Enum>();
Erçin Dedeoğlu
fonte