Question

Comment pouvez-vous énumérer un enum en 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 donne l'erreur de compilation suivante :

'Suit' est un 'type' mais est utilisé comme une 'variable'

Il échoue sur le Suit mot-clé, le deuxième.

Était-ce utile?

La solution

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

Remarque : la conversion vers (Suit[]) n'est pas strictement nécessaire, mais accélère le code de 0,5 ns.

Autres conseils

Il me semble que vous voulez vraiment imprimer les noms de chaque énumération, 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);
    }
}

Soit dit en passant, incrémenter 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 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());
    }
}

J'ai créé quelques extensions pour une utilisation facile de l'énumération, peut-être que quelqu'un pourra 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 le AttributFlags

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

Certaines versions du framework .NET ne prennent pas en charge Enum.GetValues.Voici une bonne solution de contournement de Idées 2.0 :Enum.GetValues ​​dans le cadre compact:

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 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.

Pourquoi personne n'utilise-t-il Cast<T>?

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

Vous voilà IEnumerable<Suit>.

Je pense que cela est plus efficace que d'autres suggestions car GetValues() n'est pas appelé à chaque fois que vous avez une boucle. C'est aussi plus concis. Et vous obtenez une erreur de compilation et non 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]);
        }
    }
}

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

Juste pour ajouter ma solution, qui fonctionne dans un cadre compact (3.5) et prend en charge la vérification de type à 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 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>();

Je pense que vous pouvez utiliser

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

J'ai entendu de vagues rumeurs selon lesquelles c'est   terriblement lent. Quelqu'un sait? & # 8211; Orion   Edwards 15 Oct. 08 à 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?

Trois façons:

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

Vous ne savez pas pourquoi GetEnumValues a été introduit sur l'instance de type, ce n'est pas du tout lisible pour moi.

Avoir une classe d'assistance comme Enum<T> est ce qui est le plus lisible et le plus 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 également utiliser une sorte de mise en cache si les performances comptent, mais je ne m'attends pas à ce que ce soit 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)));
    }
}

Pourquoi diable jetterai-je mes deux sous, en combinant les réponses les plus importantes, je combinerai 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));
    }
}

Nettoyer simple et par @ Jeppe-Stig-Nielsen commente rapidement.

J'utilise ToString () puis divise et analyse le tableau de sélection en indicateurs.

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

Il existe deux manières de parcourir 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 , et le second vous donnera des valeurs sous forme de tableau de String .

Utilisez-le en foreach boucle comme ci-dessous:

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

Je ne pense pas que ce soit mieux, ni même bon, mais je propose simplement une autre solution.

Si les valeurs d'énumération vont 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 de l'é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 strictement une énumération, juste une boucle.La deuxième méthode est cependant beaucoup plus rapide que toute autre approche...

Si vous avez besoin de vérifier la vitesse et le type lors de la compilation et de l'exécution, cette méthode d'assistance est préférable à 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 rapporte rien ici.

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()
      };
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(La réponse acceptée actuellement a une distribution que je ne pense pas est nécessaire (même si je peux me tromper).)

Cette question figure au chapitre 10 de & " C #. Étape par étape 2013 & ";

L’auteur utilise une double boucle for pour parcourir une paire d’énumérateurs (afin de créer un jeu de cartes complet):

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 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 PlayingCard est un objet de carte avec un <=> et <=>:

définis
class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

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

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

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

Et si vous savez que le type sera un enum, mais que vous ne connaissez pas 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 tout type d’énumération et renvoie IEnumerable toutes les valeurs d’énumération.

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

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 ensuite:

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

Ajouter 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 transmettez votre enum, vous pouvez maintenant le parcourir à l'aide de foreach

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

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 d'énumération sont considérés comme ayant un type entier "sous-jacent", ce qui signifie que chaque valeur d'énumération correspond à une valeur entière (c'est généralement implicite, mais peut être spécifié manuellement).C# a été conçu de manière à ce que vous puissiez remplir n'importe lequel entier de ce type dans la variable enum, même s'il ne s'agit pas d'une valeur "nommée".)

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

MODIFIER:J'aurais dû suggérer le Système.Enum.GetValues méthode à la place.Oops.

Vous pouvez également vous connecter directement aux membres statiques publics de l'énum à l'aide de réflexion:

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

Essayez d'utiliser foreach (élément var dans enum.getValues ​​(typeof (combinaisons)))

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top