Comment énumérer une énumération

3771

Comment pouvez-vous énumérer un enumen C #?

Par exemple, le code suivant ne compile pas:

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

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

Et cela donne l'erreur de compilation suivante:

«Suit» est un «type» mais est utilisé comme une «variable»

Il échoue sur le Suitmot - clé, le second.

Ian Boyd
la source
17
Voir aussi ... stackoverflow.com/questions/972307/…
SteveC
2
Vous voudrez peut-être vérifier les tenants et aboutissants des énumérations C # , qui en discutent ainsi que d'autres informations utiles sur l'énumération
ChaseMedallion

Réponses:

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

Remarque : le transtypage en (Suit[])n'est pas strictement nécessaire, mais il rend le code 0,5 ns plus rapide .

jop
la source
97
Cela ne fonctionne pas si vous avez des valeurs en double dans la liste des énumérateurs.
Jessy
10
Je veux juste souligner que cela, malheureusement, ne fonctionnera pas dans Silverlight, car la bibliothèque Silverlight ne comprend pas enum.GetValues. Vous devez utiliser la réflexion dans ce cas.
Giacomo Tagliabue
146
@Jessy ce fait le travail en cas de situations en double comme enum E {A = 0, B = 0}. Enum.GetValuesentraîne le renvoi de deux valeurs, bien qu'elles soient identiques. E.A == E.Best vrai, il n'y a donc pas de distinction. Si vous voulez des noms individuels, alors vous devriez chercher Enum.GetNames.
nawfal
13
Ensuite, si vous avez des doublons / synonymes dans votre énumération et que vous souhaitez l'autre comportement, vous pouvez utiliser l' Distinctextension de Linq (depuis .NET 3.5), donc foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Jeppe Stig Nielsen
42
J'ai fait l'erreur d'essayer d'utiliser varpour le type. Le compilateur crée la variable an Objectau lieu de l'énumération. Répertoriez explicitement le type d'énumération.
jpmc26
695

Il me semble que vous voulez vraiment imprimer les noms de chaque énumération plutôt que les valeurs. Dans ce cas, cela 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);
    }
}

Soit dit en passant, l'incrémentation de la valeur n'est pas un bon moyen d'énumérer les valeurs d'une énumération. Vous devriez le faire à la place.

J'utiliserais à la Enum.GetValues(typeof(Suit))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());
    }
}
Piraté
la source
2
Syntaxe VB ici: lien
AndruWitta
Je pris votre version avec un petit changement de mon côté suivant de: Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). Dans ce cas, je peux parcourir un tableau d' Suitséléments d'énumération, pas des chaînes.
Barabas
@Barabas pourquoi ne pas simplement faire Suits suit in Enum.GetValues(typeof(Suits))?
themadking
@themadking oh, mec! bien sûr, utiliser le type exact semble mieux que ce morceau monstrueux de code sh ... !
Barabas
337

J'ai fait quelques extensions pour une utilisation facile de l'énumération. 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'énumération elle-même doit être décorée avec l' attribut FlagsAttribute :

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
bob
la source
13
Une doublure pour la première méthode d'extension; ce n'est plus paresseux. return Enum.GetValues ​​(typeof (T)). Cast <T> ();
Leyu
2
Vous pouvez également utiliser OfType aussi: Enum.GetValues ​​(typeof (T)). OfType <T> (). C'est dommage qu'il n'y ait pas de version générique de GetValues ​​<T> () alors ce serait encore plus lisse.
jpierson
3
Peut-être que quelqu'un pourrait montrer comment utiliser ces extensions? Le compilateur n'affiche pas les méthodes d'extension sur enum EnumExample.
Tomas
1
quelqu'un peut-il ajouter un exemple sur la façon d'utiliser ces fonctions?
Ashwini Verma
3
+1 pour le code réutilisable: exemples - enregistrez ces méthodes d'extension dans une bibliothèque et référencez-la [Flags] public enum mytypes {name1, name2}; List <string> myTypeNames = mytypes.GetAllItems ();
Krishna
178

Certaines versions du framework .NET ne prennent pas en charge Enum.GetValues. Voici une bonne solution de contournement d' Ideas 2.0: Enum.GetValues ​​dans 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;
}

Comme pour tout code impliquant une 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.

Ekevoo
la source
18
Pourquoi ne pas utiliser le mot-clé yield ici au lieu d'instancier une liste?
Eric Mickelsen
1
ou plus court:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
nawfal
7
@nawfal: Linq n'est pas disponible .Net CF 2.0.
Gabriel GM
@Ekevoo Comment lier ces valeurs d'énumération à une DropDownList dans MVC?
Jack
115

Utilisation Cast<T>:

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

Voilà IEnumerable<Suit>.

sircodesalot
la source
1
Cela fonctionne également dans la fromclause et le foreachdéclarant d'en-tête.
Aluan Haddad
97

Je pense que c'est plus efficace que les autres suggestions car il 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 ce Suitn'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]);
        }
    }
}
James
la source
6
Attention à l'utilisation de génériques comme celui-ci. Si vous essayez d'utiliser EnumLoopun type qui n'est pas une énumération, il se compilera correctement, mais lèvera une exception au moment de l'exécution.
svick
7
Merci svick. Des exceptions d'exécution se produiront en fait avec les autres réponses de cette page ... sauf celle-ci car j'ai ajouté "où Key: struct, IConvertible" afin que vous obteniez une erreur de temps de compilation dans la plupart des cas.
James
3
Non, GetValues ​​() n'est appelée qu'une seule fois dans foreach.
Alex Blokha
4
James, je découragerais votre classe car clever est agréable à écrire mais dans le code de production que beaucoup de gens maintiendront et mettront à jour, clever est un travail supplémentaire. Si cela fait une économie importante ou sera beaucoup utilisé - donc les économies sont importantes et les gens vont se familiariser avec cela - cela en vaut la peine, mais dans la plupart des cas, cela ralentit les gens qui essaient de lire et de mettre à jour le code et introduit un possible source de bugs à l'avenir. Moins de code c'est mieux :) moins de complexité c'est encore mieux.
Grant M du
2
@GrantM Pourquoi? Ce code n'est ni complexe, ni incroyablement court. En plus de cela, l'écriture de la classe une fois permettra des itérations de code encore plus courtes avec l'utilisation selon son exemple. C'est extrêmement propre, si vous ne pouvez pas mettre à jour ce code, vous ne pouvez probablement pas mettre à jour le code d'une entreprise.
Dispersia
77

Vous n'obtiendrez pas Enum.GetValues()dans Silverlight .

Article de blog original par 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
la source
2
Belle solution, mais un refactoring sera mieux! :)
nawfal
J'utilise .NET Framework 4.0 & Silverlight enum.getvalues ​​fonctionne, le code que j'ai utilisé est ---> enum.GetValues ​​(typeof (enum))
Ananda
2
À partir de C # 7.3 (Visual Studio 2017 ≥ v15.7), on peut utiliserwhere T: Enum
Yahoo Serious
59

Ma solution fonctionne dans .NET Compact Framework (3.5) et prend en charge la vérification de type au moment de la 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 s'en débarrasser T valueType = new T(), je serais heureux de voir une solution.

Un appel ressemblerait à ceci:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
Mallox
la source
2
qu'en est-il de l'utilisation T valueType = default(T)?
Oliver
Génial, je ne connaissais même pas ce mot-clé. Toujours agréable d'apprendre quelque chose de nouveau. Je vous remercie! Renvoie-t-il toujours une référence au même objet ou crée-t-il une nouvelle instance à chaque appel de l'instruction par défaut? Je n'ai rien trouvé sur le net à ce sujet jusqu'à présent, mais si cela crée une nouvelle instance à chaque fois, cela défait en quelque sorte le but que je cherchais (avoir un one-liner ^^).
Mallox
1
Cela ne créerait-il pas une nouvelle instance pour chaque itération sur l'énumération?
Mallox
1
-1 pour "prend en charge la vérification de type au moment de la compilation:". Quel type de vérification? Cela fonctionnerait pour tout new() T. En outre, vous n'avez pas besoin new T()du tout, vous pouvez sélectionner uniquement les champs statiques et le faire .GetValue(null). Voir la réponse d'Aubrey.
nawfal
2
À partir de C # 7.3 (Visual Studio 2017 ≥ v15.7), on peut utiliserwhere T: Enum
Yahoo Serious
52

Je pense que vous pouvez utiliser

Enum.GetNames(Suit)
Tom Carr
la source
6
Enum.GetValues ​​(Suits)
Ian Boyd
50
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
Joshua Drake
la source
2
Cela énumère une chaîne, n'oubliez pas de reconvertir ces éléments en une valeur d'énumération afin que l'énumération puisse être énumérée.
Ian Boyd
1
Je vois dans votre édition que vous souhaitez réellement opérer sur les énumérations elles-mêmes, le code ci-dessus a adressé votre message d'origine.
Joshua Drake
49
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

J'ai entendu de vagues rumeurs selon lesquelles cela est terriblement lent. Quelqu'un sait? - Orion Edwards 15 octobre 2008 à 1:31 7

Je pense que la mise en cache du tableau l'accélérerait considérablement. Il semble que vous obteniez 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?

Expiation limitée
la source
5
Le compilateur devrait cependant s'en occuper.
Stephan Bijzitter
@StephanBijzitter Wow, vous lisez assez loin sur celui-ci :-) Je suis d'accord, le compilateur devrait rendre ma solution inutile.
Expiation limitée du
1
Ce n'est pas nécessaire. En regardant le code compilé dans ILSpy, le compilateur le fait certainement déjà. Pourquoi cette réponse est-elle majoritairement votée, encore moins 35 fois?
mhenry1384
1
Il a été voté il y a longtemps. Belle lurette. Je parierais que le compilateur aurait résolu cela à l'époque, cependant. Mais ça a l' air plus performant, non? ;-)
Expiation limitée
32

Trois façons:

  1. Enum.GetValues(type) // Depuis .NET 1.1, pas dans Silverlight ou .NET Compact Framework
  2. type.GetEnumValues() // Uniquement sur .NET 4 et supérieur
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Fonctionne partout

Je ne sais pas pourquoi a GetEnumValuesété introduit sur les instances de type. Ce n'est pas du tout très lisible pour moi.


Avoir une classe d'aide comme Enum<T>c'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));
    }
}

Vous appelez maintenant:

Enum<Suit>.GetValues();

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

On peut également utiliser une sorte de mise en cache si les performances sont importantes, mais je ne m'attends pas à ce que ce soit un problème du tout.

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
la source
Ceci est un joli résumé des méthodes. Je pense que vous devriez cependant fusionner votre autre réponse. La vérité est que l'énumération est spéciale et leur boucle est souvent (généralement) tout aussi valide que l'énumération car vous savez que les valeurs ne changeront jamais. IOW, si vous avez une énumération qui change tout le temps, vous avez choisi la mauvaise construction de données pour commencer.
krowe2
31

En combinant les meilleures réponses, j'ai créé 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 T value) where T : Enum
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

C'est propre, simple et, par le commentaire de @ Jeppe-Stig-Nielsen, rapide.

Côté obscur
la source
6
À partir de C # 7.3 (Visual Studio 2017 ≥ v15.7), on peut utiliserwhere T: Enum
Yahoo Serious
24

Il existe deux façons d'itérer un Enum:

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

Le premier vous donnera des valeurs sous forme sur un tableau de ** object** s, et le second vous donnera des valeurs sous forme d'un tableau de **String ** s.

Utilisez-le en foreachboucle comme ci-dessous:

foreach(var value in values)
{
    // Do operations here
}
Kylo Ren
la source
2
Peut-être que cela est déjà couvert dans de nombreuses réponses? Ne rendons pas les réponses redondantes.
nawfal
@nawfal yes peut être couvert dans d'autres réponses, mais pas bien conclu dans la plupart d'entre elles.
Kylo Ren
23

J'utilise ToString (), puis je scinde et analyse le tableau Spit dans des 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);
}
Mickey Perlstein
la source
17

Je ne pense pas que ce soit mieux, ni même bon. Je ne fais qu'énoncer une autre solution.

Si les valeurs enum vont strictement de 0 à n - 1, une alternative générique est:

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 d'énumération sont contiguës et que vous pouvez fournir le premier et le dernier élément de l'énumération, 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 cependant beaucoup plus rapide que toute autre approche ...

nawfal
la source
16

Si vous avez besoin d'une vérification de la vitesse et du type lors de la génération et de l'exécution, cette méthode d'assistance est meilleure que l'utilisation de LINQ pour convertir 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 revenir IEnumerable<T>, mais cela ne vous achète rien ici.

dmihailescu
la source
3
À partir de C # 7.3 (Visual Studio 2017 ≥ v15.7), on peut utiliserwhere T: Enum
Yahoo Serious
14

Voici un exemple pratique de création d'options de sélection 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()
      };
jhilden
la source
10
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(La réponse actuellement acceptée a un casting que je ne pense pas nécessaire (bien que je puisse me tromper).)

brûlures mates
la source
10

Cette question apparaît dans le chapitre 10 de « C # étape par étape 2013 »

L'auteur utilise une double boucle for pour parcourir une paire d'énumérateurs (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, Suitet Valuesont les 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 PlayingCardest un objet de carte avec un défini Suitet 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
la source
Est-ce que cela fonctionnera si les valeurs enum ne sont pas séquentielles?
Aamir Masood
10

Je sais que c'est un peu compliqué, mais si vous êtes fan de one-liners, en voici un:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
anar khalilov
la source
2
C'est vif ?
Mikael Dúi Bolinder
8

Et si vous savez que le type sera un enum, mais 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 getListOfEnumutilise la réflexion pour prendre n'importe quel type d'énumération et renvoie une IEnumerablede toutes les valeurs d'énumération.

Usage:

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
la source
8

Un moyen simple et générique de convertir une énumération 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 alors:

var enums = EnumHelper.ToList<MyEnum>();
Gabriel
la source
A Dictionaryn'est pas une bonne idée: si vous avez un Enumcomme enum E { A = 0, B = 0 }, la valeur 0 est ajoutée 2 fois générant un ArgumentException(vous ne pouvez pas ajouter la même Keysur une Dictionary2 fois ou plus!).
Massimiliano Kraus du
Pourquoi renvoyer un Dictionary<,>depuis une méthode nommée ToList? Et pourquoi ne pas revenir Dictionary<T, string>?
Aluan Haddad
8

Ajoutez une méthode public static IEnumerable<T> GetValues<T>()à votre classe, comme:

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

Appelez et passez votre énumération. Vous pouvez maintenant le parcourir en utilisant foreach:

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

enumles types sont appelés "types d'énumération" non pas parce qu'ils sont des conteneurs qui "énumèrent" les valeurs (ce qu'ils ne sont pas), mais parce qu'ils sont définis en énumérant 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 (ceci est généralement implicite, mais peut être spécifié manuellement). C # a été conçu de manière à pouvoir bourrer n'importe quel entier de ce type dans la variable enum, même s'il ne s'agit pas d'une valeur "nommée".)

La méthode System.Enum.GetNames peut être utilisée pour récupérer un tableau de chaînes qui sont les noms des valeurs d'énumération, comme son nom l'indique.

EDIT: aurait dû suggérer la méthode System.Enum.GetValues ​​à la place. Oops.

Emily Chen
la source
2
Bien que votre réponse soit correcte en elle-même, elle ne répond pas vraiment à la question initiale du PO. La GetNamesméthode renvoie, en effet, un tableau de chaînes, mais l'OP nécessite un énumérateur à travers les valeurs.
Silviu Preda du
@SilviuPreda: modifié. Il aurait dû s'agir de GetValues ​​au lieu de GetNames.
Emily Chen
2

J'ai essayé de nombreuses façons et obtenu le résultat de ce code:

Pour obtenir une liste d'int à partir d'une énumération, utilisez ce qui suit. Ça marche!

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

Vous pouvez également vous lier directement aux membres statiques publics de l'énumération en utilisant la réflexion:

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

Si tu as:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Cette:

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

Sortira:

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

LINQ Generic Way:

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

Usage:

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