Comment puis-je énumérer un enum en C#?

Comment Pouvez-vous énumérer un enum dans C#?

E. G. le code suivant Ne se compile pas:

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

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

et donne l'erreur de compilation suivante:

de "Costume" est un "type" mais est utilisée comme une "variable"

il échoue sur le mot-clé Suit , le second.

3189
demandé sur Cœur 2008-09-20 00:34:50

26 réponses

foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}
3963
répondu jop 2018-06-21 08:23:55

il me semble que vous voulez vraiment imprimer les noms de chaque enum, plutôt que les valeurs. Dans ce cas, Enum.GetNames() semble être la bonne approche.

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

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

Par ailleurs, l'incrémentation de la valeur n'est pas une bonne façon d'énumérer les valeurs d'une énumération. Vous devez faire cela à la place.

j'utiliserais Enum.GetValues(typeof(Suit)) à la place.

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

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}
579
répondu Haacked 2014-02-10 18:04:36

j'ai fait quelques extensions pour l'utilisation facile d'enum, peut-être que quelqu'un peut l'utiliser...

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

l'enum lui-même doit être décoré avec le FlagsAttribute

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
291
répondu bob 2010-12-07 16:53:32

certaines versions du .net framework ne prennent pas en charge Enum.GetValues . Voici une bonne solution de contournement de idées 2.0: Enum.GetValues in Compact Framework :

public List<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.GetValue(enumeration));
   }
   return enumerations;
}

comme pour tout code qui implique réflexion , vous devez prendre des mesures pour vous assurer qu'il ne s'exécute qu'une seule fois et que les résultats sont mis en cache.

151
répondu Ekevoo 2017-08-19 03:04:48

je pense que c'est plus efficace que d'autres suggestions parce que GetValues() n'est pas appelé chaque fois que vous avez une boucle. Il est également plus concis. Et vous obtenez une erreur de compilation pas une exception d'exécution si Suit n'est pas un enum .

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

EnumLoop a cette définition complètement Générique:

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]);
        }
    }
}
86
répondu James 2016-03-17 19:41:48

pourquoi personne n'utilise Cast<T> ?

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

et voilà IEnumerable<Suit> .

83
répondu sircodesalot 2014-07-25 12:12:52

vous n'aurez pas Enum.GetValues() à Silverlight.

billet original du Blog 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();
    }
}
68
répondu Aubrey Taylor 2016-01-15 14:11:29

juste pour ajouter ma solution, qui fonctionne dans le cadre compact (3.5) et soutient le contrôle de type à l'Heure de compilation :

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

- si quelqu'un sait comment se débarrasser du T valueType = new T() , je serais heureux de voir une solution.

un appel ressemblerait à ceci:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
51
répondu Mallox 2014-01-30 04:43:03

je pense que vous pouvez utiliser

Enum.GetNames(Suit)
45
répondu Tom Carr 2011-07-25 07:46:06
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
42
répondu Joshua Drake 2017-01-09 20:45:39
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

j'ai entendu de vagues rumeurs que c'est terifically slow. Tout le monde sait? – Orion Edwards Oct 15 ' 08 à 1: 31 7

je pense que la mise en cache du tableau l'accélérerait considérablement. On dirait que vous obtenez un nouveau tableau (par réflexion) à chaque fois. Plutôt:

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

C'est au moins un peu plus rapide, ja?

37
répondu Limited Atonement 2017-10-06 07:20:14

trois voies:

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

Je ne sais pas pourquoi GetEnumValues a été introduit sur l'instance de type, il n'est pas très lisible du tout pour moi.


avoir une classe d'aide comme Enum<T> est ce qui est le plus lisible et mémorable pour moi:

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

Maintenant vous appelez:

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

on peut aussi utiliser une sorte de cache si la performance importe, mais je ne vous attendez pas à être un problème

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)));
    }
}
21
répondu nawfal 2017-01-09 23:43:50

Ce que l'enfer je vais jeter mes deux pence, juste en combinant les réponses les plus fréquentes que je travers ensemble une extension très simple

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)
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

Propre et simple par @Jeppe-Stig-Nielsen s commentaire rapide.

20
répondu Darkside 2013-06-15 08:22:46

j'utilise ToString() puis je divise et parse le tableau spit en Drapeaux.

[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);
}
19
répondu Mickey Perlstein 2015-11-18 15:51:19

il y a deux façons d'itérer un Enum :

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

La première sera de vous donner les valeurs en forme sur un tableau de object , et le second vous donnera des valeurs sous forme de tableau de String .

utilisez-le dans foreach boucle comme ci-dessous:

foreach(var value in values)
{
    //Do operations here
}
19
répondu Kylo Ren 2017-01-13 07:12:47

Je ne suis pas d'avis que c'est mieux, ou même bon, de simplement énoncer une autre solution.

si les valeurs enum varient strictement de 0 à n-1, une alternative Générique:

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

si les valeurs enum sont contiguës et que vous pouvez fournir le premier et le dernier élément de l'enum, alors:

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

mais ce n'est pas une énumération stricte, juste une boucle. La deuxième méthode est beaucoup plus rapide que toute autre approche bien...

13
répondu nawfal 2013-01-25 00:05:04

si vous avez besoin d'un contrôle de vitesse et de type au temps de construction et d'exécution, cette méthode d'aide est meilleure que L'utilisation de LINQ pour mouler chaque élément:

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

Et vous pouvez l'utiliser comme ci-dessous:

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

bien sûr, vous pouvez retourner IEnumerable<T> , mais que vous achète rien ici.

13
répondu dmihailescu 2016-01-17 12:11:23

voici un exemple pratique de création d'options select pour un 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()
      };
11
répondu jhilden 2015-10-02 14:00:04
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(Le courant a accepté de répondre a un casting que je ne pense pas que est nécessaire (bien que je puisse me tromper).)

9
répondu matt burns 2016-01-17 12:12:22

cette question apparaît au chapitre 10 de " C# étape par étape 2013 "

l'auteur utilise une double boucle pour itérer à travers une paire d'enquêteurs (pour créer un jeu complet de cartes):

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

dans ce cas, Suit et Value sont deux énumérations:

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

et PlayingCard est un objet de carte défini Suit et Value :

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

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}
8
répondu Ross Gatih 2017-01-13 07:22:21

je sais que c'est un peu bordélique, mais si vous êtes fan des monocouches, en voici un:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
6
répondu anar khalilov 2015-05-15 11:31:39

une façon simple et générique de convertir un enum en quelque chose que vous pouvez 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());
}

et ensuite:

var enums = EnumHelper.ToList<MyEnum>();
6
répondu Gabriel 2016-10-25 14:12:37

Que faire si vous savez que le type sera un enum , mais que vous ne savez pas quel est le type exact au moment de la compilation?

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

la méthode getListOfEnum utilise la réflexion pour prendre n'importe quel type d'enum et renvoie un IEnumerable de toutes les valeurs d'enum.

Utilisation:

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));
}
5
répondu Slappywag 2015-10-01 10:21:40

ajouter la méthode public static IEnumerable<T> GetValues<T>() à votre classe, comme

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

appeler et passer votre enum, maintenant vous pouvez itérer à travers elle en utilisant foreach

 public static void EnumerateAllSuitsDemoMethod()
 {
     // custom method
     var foos = GetValues<Suit>(); 
     foreach (var foo in foos)
     {
         // Do something
     }
 }
1
répondu MUT 2017-10-06 07:18:22

vous pouvez aussi lier directement au public les membres statiques de l'enum en utilisant la réflexion:

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
    .ToList().ForEach(x => DoSomething(x.Name));
0
répondu Termininja 2017-01-09 23:39:34

enum les types sont appelés "types d'énumération" non pas parce qu'ils sont des conteneurs qui "énumèrent" des valeurs (ce qu'ils ne sont pas), mais parce qu'ils sont définis par énumérer les valeurs possibles pour une variable de ce type.

(en fait, c'est un peu plus compliqué que cela - les types enum sont considérés comme ayant un type entier "sous-jacent", ce qui signifie que chaque valeur enum correspond à une valeur entière (ce qui est généralement implicite, mais peut être spécifié manuellement). C# a été conçu de manière à ce que vous puissiez insérer n'importe quel "entier 151930920" de ce type dans la variable enum, même si ce n'est pas une valeur "nommée".)

Le Système .Enum.La méthode GetNames peut être utilisée pour récupérer un tableau de chaînes qui sont les noms des valeurs enum, comme leur nom l'indique.

modifier: aurait dû suggérer le système .Enum.GetValues méthode plutôt. Oops.

-1
répondu Emily Chen 2018-01-16 20:14:54