Pergunta

Como você pode enumerar uma enum em 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 dá o seguinte erro de tempo de compilação:

'terno' é um 'tipo' mas é usado como uma 'variável'

Ele falha na palavra-chave Suit, o segundo.

Foi útil?

Solução

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

Nota : O elenco de (Suit[]) não é estritamente necessário, mas faz o código de 0,5 ns mais rápido.

Outras dicas

Parece-me que você realmente quer imprimir os nomes de cada enum, em vez dos valores. Caso em que 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, incrementando o valor não é uma boa maneira para enumerar os valores de uma enumeração. Você deve fazer isso em seu lugar.

Gostaria de usar Enum.GetValues(typeof(Suit)) vez.

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

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}

Eu fiz algumas extensões para o uso enum fácil, talvez alguém pode 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;
    }
}

O enum em si deve ser decorado com a FlagsAttribute

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}

Algumas versões do framework .NET não suportam Enum.GetValues. Aqui está uma boa solução de Ideias 2.0: Enum.GetValues ??em 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;
}

Tal como acontece com qualquer código que envolve href="https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection" , você deve tomar medidas para garantir que ele é executado apenas uma vez e os resultados são armazenados em cache.

Porque é que ninguém usando Cast<T>?

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

Lá você vai IEnumerable<Suit>.

Eu acho que isso é mais eficiente do que outras sugestões porque GetValues() não é chamado cada vez que você tem um loop. É também mais concisa. E você recebe um erro de tempo de compilação e não uma exceção tempo de execução se Suit não é uma enum.

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

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

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]);
        }
    }
}

Você não terá Enum.GetValues() em Silverlight.

Blog original Mensagem por 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();
    }
}

Só para acrescentar a minha solução, que funciona no quadro compacto (3.5) e suportes 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 sabe como se livrar do T valueType = new T(), eu ficaria feliz em ver uma solução

Uma chamada ficaria assim:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();

Eu acho que você pode usar

Enum.GetNames(Suit)
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

Eu ouvi rumores vagos de que este é terifically lento. Ninguem sabe? - Orion Edwards 15 de outubro '08 em 1:31 7

Eu acho que o cache da matriz iria acelerar consideravelmente. Parece que você está recebendo uma nova matriz (por meio de reflexão) de cada vez. Pelo contrário:

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

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

Três maneiras:

1. Enum.GetValues(type) //since .NET 1.1, not in silverlight or compact framewok
2. type.GetEnumValues() //only on .NET 4 and above
3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) //works everywhere

Não sei por que foi GetEnumValues introduzido no tipo de instância, não é muito legível em tudo para mim.


Ter uma classe auxiliar como Enum<T> é o que é 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ê chama:

Enum<Suit>.GetValues();
//or
Enum.GetValues(typeof(Suit)); //pretty consistent style

Pode-se também utilizar tipo de cache, se o desempenho é importante, mas eu não espero que isso seja um problema em tudo

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)));
    }
}

O que diabos eu vou jogar meus dois pence em, apenas, combinando as principais respostas que passamos juntos 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));
    }
}

simples Limpo e por @ comentário Jeppe-Stig-Nielsen s rápido.

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

[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);
}

Há duas maneiras para fazer uma iteração uma Enum:

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

O primeiro vai lhe dar valores em forma em uma variedade de object , eo segundo vai lhe dar valores em forma de leque de String .

Use-o em ciclo foreach como abaixo:

foreach(var value in values)
{
    //Do operations here
}

Eu não segurar a opinião isso é melhor, ou mesmo bom, apenas afirmando ainda uma outra solução.

Se os valores 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 de enumeração são contíguas e você pode fornecer o primeiro e ú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 enumerar, apenas looping. O segundo método é muito mais rápido do que qualquer outra abordagem embora ...

Se você precisa de velocidade e verificação de tipo em construção e tempo de execução, este método auxiliar é melhor do que usar LINQ para lançar 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 retornar IEnumerable<T>, mas que você compra nada aqui.

aqui é um exemplo de trabalho de criação de selecionar opções para um 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()
      };
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

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

Esta questão aparece no capítulo 10 do " C # Passo a passo 2013 "

O autor usa um double loop for para percorrer um par de Enumerators (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);
            }
        }
    }
}

Neste caso, Suit e Value são ambos 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 cartão com um Suit e Value definido:

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

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}

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

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));

E se você sabe o tipo será um enum, mas você não sabe o que o tipo exato é em tempo de 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 getListOfEnum usa reflexão para tomar qualquer tipo de enumeração e retorna um IEnumerable de 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));
}

Uma maneira simples e genérica para converter um enum para 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, em seguida:

var enums = EnumHelper.ToList<MyEnum>();

Adicionar método public static IEnumerable<T> GetValues<T>() a sua classe, como

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

chamada e passar o seu enum, agora você pode interagir com ele usando foreach

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

tipos enum são chamados de "tipos de enumeração" não porque eles são recipientes que os valores "Enumerar" (que não são), mas porque eles são definidos pela enumerando os valores possíveis para uma variável de desse tipo.

(Na verdade, isso é um pouco mais complicado do que isso - tipos enum são considerados como tendo um "subjacente" tipo inteiro, o que significa cada valor enum corresponde a um valor inteiro (este é normalmente implícita, mas pode ser especificado manualmente). C # foi concebido de uma forma para que você possa encher qualquer inteiro desse tipo na variável enum, mesmo que isso não é um "chamado" valor).

O System.Enum método .GetNames pode ser usado para recuperar uma matriz de cadeias que são os nomes dos valores enum, como o nome sugere.

EDIT: Deveria ter sugerido o System.Enum.GetValues ?? método em vez. Opa.

Além disso, você pode ligar para os membros estáticos públicos da enum diretamente usando reflexão:

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

tente usar foreach (var item em Enum.GetValues ??(typeof (ternos)))

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top