[C#] Comment puis-je itérer sur une énumération?



Answers

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

Au fait, 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)) 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());
    }
}
Question

Comment pouvez-vous énumérer une 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 mot-clé Suit , le second.




Qu'est-ce que je vais jeter mes deux pence, juste en combinant les meilleures réponses que je traverse 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));
    }
}

Nettoyer simple et par @ Jeppe-Stig-Nielsen s commenter rapidement.




enum types enum sont appelés "types d'énumération" non pas parce que ce sont des conteneurs qui "énumèrent" des valeurs (ce qui n'est pas le cas), 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 ça - 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 typiquement implicite, mais peut être spécifié manuellement). d'une manière telle que vous puissiez insérer tout entier de ce type dans la variable enum, même si ce n'est pas 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 enum, comme son nom l'indique.

EDIT: Doit avoir suggéré la méthode System.Enum.GetValues place. Oops.




Juste pour ajouter ma solution, qui fonctionne dans un cadre compact (3.5) et supporte 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 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 ne suis pas d'avis que c'est mieux, voire même bon, que d'énoncer une autre solution.

Si les valeurs enum 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 enum 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 énumérer strictement, juste en boucle. La deuxième méthode est beaucoup plus rapide que toute autre approche si ...




J'utilise ToString () puis diviser et analyser le tableau spit dans les 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);
}



Pourquoi personne n'utilise Cast<T> ?

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

Là vous allez IEnumerable<Suit> .




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



Certaines versions du framework .NET ne prennent pas en charge Enum.GetValues . Voici une bonne solution de contournement de Ideas 2.0: Enum.GetValues ​​dans 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 impliquant une reflection , vous devez prendre des mesures pour vous assurer qu'il s'exécute une seule fois et que les résultats sont mis en cache.




Une manière 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>();



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



Cette question apparaît au chapitre 10 de " C # Step by Step 2013 "

L'auteur utilise une double boucle 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, 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 Suit et une Value définis:

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

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



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

appelez et passez votre énumération, 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
     }
 }





Links