Wie man eine Aufzählung auflistet

3766

Wie können Sie ein enumin C # aufzählen ?

ZB wird der folgende Code nicht kompiliert:

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

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

Und es gibt den folgenden Fehler beim Kompilieren:

'Anzug' ist ein 'Typ', wird aber wie eine 'Variable' verwendet.

Das SuitSchlüsselwort, das zweite, schlägt fehl .

Ian Boyd
quelle
17
Siehe auch ... stackoverflow.com/questions/972307/…
SteveC
2
Vielleicht möchten Sie sich die Vor- und Nachteile von C # -Aufzählungen ansehen , in denen dies sowie andere nützliche Aufzählungs-Leckerbissen
erläutert werden

Antworten:

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

Hinweis : Die Umwandlung in (Suit[])ist nicht unbedingt erforderlich, beschleunigt jedoch den Code um 0,5 ns .

jop
quelle
97
Dies funktioniert nicht, wenn Sie doppelte Werte in der Enumeratorliste haben.
Jessy
10
Ich möchte nur darauf hinweisen, dass dies in Silverlight leider nicht funktioniert, da die Silverlight-Bibliothek nicht umfasst enum.GetValues. In diesem Fall müssen Sie Reflexion verwenden.
Giacomo Tagliabue
146
@Jessy das funktioniert bei doppelten Situationen wie enum E {A = 0, B = 0}. Enum.GetValuesführt dazu, dass zwei Werte zurückgegeben werden, obwohl sie gleich sind. E.A == E.Bist wahr, also gibt es keinen Unterschied. Wenn Sie individuelle Namen möchten, sollten Sie suchen Enum.GetNames.
Nawfal
13
Wenn Sie dann Duplikate / Synonyme in Ihrer Aufzählung haben und das andere Verhalten wünschen, können Sie die Linq- DistinctErweiterung (seit .NET 3.5) verwenden foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Jeppe Stig Nielsen
42
Ich habe den Fehler gemacht, varfür den Typ zu verwenden. Der Compiler macht die Variable zu einer Objectanstelle der Aufzählung. Listen Sie den Aufzählungstyp explizit auf.
jpmc26
695

Es sieht für mich so aus, als ob Sie wirklich die Namen jeder Aufzählung und nicht die Werte ausdrucken möchten. In diesem Fall Enum.GetNames()scheint der richtige Ansatz zu sein.

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

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

Das Inkrementieren des Werts ist übrigens keine gute Möglichkeit, die Werte einer Aufzählung aufzulisten. Sie sollten dies stattdessen tun.

Ich würde Enum.GetValues(typeof(Suit))stattdessen verwenden.

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

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}
Gehackt
quelle
2
VB Syntax hier: Link
AndruWitta
Ich habe Ihre Version mit ein paar kleinen Änderungen von meiner Seite genommen : Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). In diesem Fall kann ich ein Array von SuitsAufzählungselementen iterieren , keine Zeichenfolgen.
Barabas
@ Barabas warum nicht einfach tun Suits suit in Enum.GetValues(typeof(Suits))?
Der
@themadking oh Mann! Natürlich sieht die Verwendung des exakten Typs besser aus als dieses monströse Stück Sh ... Code!
Barabas
337

Ich habe einige Erweiterungen für die einfache Verwendung von Enum gemacht. Vielleicht kann es jemand benutzen ...

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

Die Aufzählung selbst muss mit dem FlagsAttribute verziert sein :

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
Bob
quelle
13
Ein Einzeiler für die erste Verlängerungsmethode; es ist nicht mehr faul. return Enum.GetValues ​​(typeof (T)). Cast <T> ();
Leyu
2
Alternativ können Sie auch OfType verwenden: Enum.GetValues ​​(typeof (T)). OfType <T> (). Es ist schade, dass es keine generische Version von GetValues ​​<T> () gibt, dann wäre es noch schlauer.
Jpierson
3
Vielleicht könnte jemand zeigen, wie man diese Erweiterungen benutzt? Der Compiler zeigt keine Erweiterungsmethoden in enum EnumExample an.
Tomas
1
Kann jemand ein Beispiel hinzufügen, wie man diese Funktionen nutzt?
Ashwini Verma
3
+1 für wiederverwendbaren Code: Beispiele - Speichern Sie diese Erweiterungsmethoden in einer Bibliothek und verweisen Sie darauf. [Flags] public enum mytypes {name1, name2}; List <string> myTypeNames = mytypes.GetAllItems ();
Krishna
178

Einige Versionen des .NET Frameworks werden nicht unterstützt Enum.GetValues. Hier ist eine gute Problemumgehung von Ideas 2.0: Enum.GetValues ​​in 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;
}

Wie bei jedem Code, der Reflexion beinhaltet , sollten Sie Schritte unternehmen, um sicherzustellen, dass er nur einmal ausgeführt wird und die Ergebnisse zwischengespeichert werden.

Ekevoo
quelle
18
Warum nicht hier das Schlüsselwortield verwenden, anstatt eine Liste zu instanziieren?
Eric Mickelsen
1
oder kürzer:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
Nawfal
7
@nawfal: Linq ist nicht verfügbar. Net CF 2.0.
Gabriel GM
@Ekevoo Wie binde ich diese Aufzählungswerte an eine DropDownList in MVC?
Jack
115

Verwendung Cast<T>:

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

Los geht's IEnumerable<Suit>.

sircodesalot
quelle
1
Dies funktioniert auch in der fromKlausel und im foreachHeader-Deklarator.
Aluan Haddad
97

Ich denke, dies ist effizienter als andere Vorschläge, da GetValues()es nicht jedes Mal aufgerufen wird, wenn Sie eine Schleife haben. Es ist auch prägnanter. Und Sie erhalten einen Fehler zur Kompilierungszeit, keine Laufzeitausnahme, wenn dies Suitkeine ist enum.

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

EnumLoop hat diese völlig generische Definition:

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
quelle
6
Vorsichtig mit solchen Generika umgehen. Wenn Sie versuchen, EnumLoopeinen Typ zu verwenden, der keine Aufzählung ist, wird er problemlos kompiliert, löst jedoch zur Laufzeit eine Ausnahme aus.
Svick
7
Danke svick. Bei den anderen Antworten auf dieser Seite treten tatsächlich Laufzeitausnahmen auf ... mit Ausnahme dieser, da ich "where Key: struct, IConvertible" hinzugefügt habe, sodass in den meisten Fällen ein Fehler bei der Kompilierung auftritt.
James
3
Nein, GetValues ​​() wird im foreach nur einmal aufgerufen.
Alex Blokha
4
James, ich würde deine Klasse entmutigen, weil clever nett zu schreiben ist, aber in Produktionscode, den viele Leute pflegen und aktualisieren, ist clever zusätzliche Arbeit. Wenn es eine große Einsparung macht oder viel genutzt wird - die Einsparungen sind also groß und die Leute werden damit vertraut -, lohnt es sich, aber in den meisten Fällen verlangsamt es die Leute, die versuchen, den Code zu lesen und zu aktualisieren, und führt eine mögliche ein Quellfehler in der Zukunft. Weniger Code ist besser :) Weniger Komplexität ist noch besser.
Grant M
2
@GrantM Warum? Dieser Code ist weder komplex noch unglaublich kurz. Darüber hinaus ermöglicht das einmalige Schreiben der Klasse noch kürzere Iterationen des Codes bei Verwendung gemäß seinem Beispiel. Dies ist äußerst sauber. Wenn Sie diesen Code nicht aktualisieren können, können Sie wahrscheinlich keinen der Firmencodes aktualisieren.
Dispersia
77

Sie werden nicht Enum.GetValues()in Silverlight bekommen .

Originaler Blogbeitrag von 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
quelle
2
Gute Lösung, aber einige Umgestaltungen werden besser sein! :)
Nawfal
Ich verwende .NET Framework 4.0 & silverlight enum.getvalues ​​funktioniert, der Code, den ich verwendet habe, ist ---> enum.GetValues ​​(typeof (enum))
Ananda
2
Ab C # 7.3 (Visual Studio 2017 ≥ v15.7) kann man verwendenwhere T: Enum
Yahoo Serious
59

Meine Lösung funktioniert in .NET Compact Framework (3.5) und unterstützt die Typprüfung beim Kompilieren :

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();
}
  • Wenn jemand weiß, wie man das loswird T valueType = new T(), würde ich mich über eine Lösung freuen.

Ein Anruf würde so aussehen:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
Mallox
quelle
2
was ist mit verwenden T valueType = default(T)?
Oliver
Großartig, ich kannte dieses Schlüsselwort nicht einmal. Immer schön etwas Neues zu lernen. Vielen Dank! Gibt es immer einen Verweis auf dasselbe Objekt zurück oder erstellt es jedes Mal eine neue Instanz, wenn die Standardanweisung aufgerufen wird? Ich habe bisher noch nichts im Internet darüber gefunden, aber wenn jedes Mal eine neue Instanz erstellt wird, wird der von mir gesuchte Zweck (mit einem Einzeiler ^^) irgendwie zunichte gemacht.
Mallox
1
Würde dies nicht für jede Iteration über die Aufzählung eine neue Instanz erstellen?
Mallox
1
-1 für "unterstützt die Typprüfung zur Kompilierungszeit:". Welche Typprüfung? Dies würde für jeden funktionieren new() T. Außerdem brauchen Sie new T()überhaupt nicht, Sie können nur die statischen Felder allein auswählen und tun .GetValue(null). Siehe Aubreys Antwort.
Nawfal
2
Ab C # 7.3 (Visual Studio 2017 ≥ v15.7) kann man verwendenwhere T: Enum
Yahoo Serious
52

Ich denke du kannst es benutzen

Enum.GetNames(Suit)
Tom Carr
quelle
6
Enum.GetValues ​​(Anzüge)
Ian Boyd
50
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
Joshua Drake
quelle
2
Vergessen Sie nicht, diese Dinge wieder in einen Aufzählungswert umzuwandeln, damit die Aufzählung aufgezählt werden kann.
Ian Boyd
1
Ich sehe aus Ihrer Bearbeitung, dass Sie tatsächlich die Aufzählungen selbst bearbeiten möchten. Der obige Code hat Ihren ursprünglichen Beitrag adressiert.
Joshua Drake
49
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

Ich habe vage Gerüchte gehört, dass dies sehr langsam ist. Weiß jemand? - Orion Edwards 15. Oktober 08 um 1:31 7

Ich denke, das Zwischenspeichern des Arrays würde es erheblich beschleunigen. Es sieht so aus, als würden Sie jedes Mal ein neues Array (durch Reflexion) erhalten. Lieber:

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

Das ist zumindest etwas schneller, ja?

Begrenzte Versöhnung
quelle
5
Der Compiler sollte sich jedoch darum kümmern.
Stephan Bijzitter
@StephanBijzitter Wow, du liest ziemlich weit unten :-) Ich stimme zu, der Compiler sollte meine Lösung unnötig machen.
Begrenzte Versöhnung
1
Dies ist nicht erforderlich. Wenn man sich den kompilierten Code in ILSpy ansieht, macht der Compiler dies definitiv schon. Warum wird diese Antwort überhaupt positiv bewertet, geschweige denn 35 Mal?
Mhenry1384
1
Es wurde vor langer Zeit positiv bewertet. Vor sehr langer Zeit. Ich würde wetten, dass der Compiler dies damals auch gelöst hätte. Aber es sieht sicher performanter aus, nicht wahr? ;-)
Begrenzte Versöhnung
32

Drei Wege:

  1. Enum.GetValues(type) // Seit .NET 1.1 nicht in Silverlight oder .NET Compact Framework
  2. type.GetEnumValues() // Nur unter .NET 4 und höher
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Funktioniert überall

Ich bin nicht sicher, warum GetEnumValuesauf Typinstanzen eingeführt wurde. Es ist für mich überhaupt nicht sehr lesbar.


Eine Helferklasse wie diese zu haben, Enum<T>ist für mich am lesbarsten und unvergesslichsten:

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

Jetzt rufst du an:

Enum<Suit>.GetValues();

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

Man kann auch eine Art Caching verwenden, wenn es auf die Leistung ankommt, aber ich erwarte nicht, dass dies überhaupt ein Problem ist.

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
quelle
Dies ist eine schöne Zusammenfassung der Methoden. Ich denke, Sie sollten Ihre andere Antwort darin zusammenführen. Die Wahrheit ist, dass Enum etwas Besonderes ist und das Durchlaufen oft (normalerweise) genauso gültig ist wie Enumeration, weil Sie wissen, dass sich die Werte niemals ändern werden. IOW, Wenn Sie eine Aufzählung haben, die sich ständig ändert, haben Sie zunächst das falsche Datenkonstrukt ausgewählt.
Krowe2
31

Nur durch die Kombination der Top-Antworten habe ich eine sehr einfache Erweiterung zusammengestellt:

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

Es ist sauber, einfach und laut @ Jeppe-Stig-Nielsens Kommentar schnell.

Dunkle Seite
quelle
6
Ab C # 7.3 (Visual Studio 2017 ≥ v15.7) kann man verwendenwhere T: Enum
Yahoo Serious
24

Es gibt zwei Möglichkeiten, ein zu iterieren Enum:

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

Der erste gibt Ihnen Werte in Form auf einem Array von ** object** s und der zweite gibt Ihnen Werte in Form eines Arrays von ** String** s.

Verwenden Sie es in einer foreachSchleife wie folgt:

foreach(var value in values)
{
    // Do operations here
}
Kylo Ren
quelle
2
Vielleicht, weil dies bereits in vielen Antworten behandelt wird? Lassen Sie uns Antworten nicht überflüssig machen.
Nawfal
@nawfal yes wird möglicherweise in anderen Antworten behandelt, obwohl es in den meisten von ihnen nicht gut abgeschlossen ist.
Kylo Ren
23

Ich benutze ToString () und teile und analysiere das Spit-Array in Flags.

[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
quelle
17

Ich bin nicht der Meinung, dass dies besser oder sogar gut ist. Ich sage nur noch eine andere Lösung.

Wenn die Enum-Werte streng zwischen 0 und n - 1 liegen, ist eine generische Alternative:

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

Wenn Aufzählungswerte zusammenhängend sind und Sie das erste und letzte Element der Aufzählung angeben können, dann:

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

Aber das ist keine strikte Aufzählung, sondern nur eine Schleife. Die zweite Methode ist jedoch viel schneller als jeder andere Ansatz ...

nawfal
quelle
16

Wenn Sie zur Erstellung und Laufzeit eine Geschwindigkeits- und Typprüfung benötigen, ist diese Hilfsmethode besser als die Verwendung von LINQ zum Umwandeln jedes Elements:

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

Und Sie können es wie folgt verwenden:

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

Natürlich können Sie zurückkehren IEnumerable<T>, aber das bringt Ihnen hier nichts.

dmihailescu
quelle
3
Ab C # 7.3 (Visual Studio 2017 ≥ v15.7) kann man verwendenwhere T: Enum
Yahoo Serious
14

Hier ist ein Arbeitsbeispiel zum Erstellen von Auswahloptionen für eine 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
quelle
10
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(Die aktuell akzeptierte Antwort hat eine Besetzung, die ich nicht für nötig halte (obwohl ich mich möglicherweise irre).)

matte Verbrennungen
quelle
10

Diese Frage erscheint in Kapitel 10 von " C # Step by Step 2013 ".

Der Autor verwendet eine doppelte for-Schleife, um zwei Enumeratoren zu durchlaufen (um ein vollständiges Kartenspiel zu erstellen):

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

In diesem Fall Suitund Valuesind beide Aufzählungen:

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

und PlayingCardist ein Kartenobjekt mit einem definierten Suitund 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
quelle
Funktioniert dies, wenn die Werte in enum nicht sequentiell sind?
Aamir Masood
10

Ich weiß, dass es ein bisschen chaotisch ist, aber wenn Sie ein Fan von Einzeiler sind, hier ist einer:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
anar khalilov
quelle
2
Ist das lispeln ?
Mikael Dúi Bolinder
8

Was ist, wenn Sie wissen, dass der Typ ein enumTyp ist, Sie aber nicht wissen, wie der genaue Typ zur Kompilierungszeit lautet?

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

Die Methode getListOfEnumverwendet Reflektion, um einen beliebigen Aufzählungstyp zu verwenden, und gibt einen IEnumerablealler Aufzählungswerte zurück.

Verwendungszweck:

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
quelle
8

Eine einfache und allgemeine Möglichkeit, eine Aufzählung in etwas umzuwandeln, mit dem Sie interagieren können:

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

Und dann:

var enums = EnumHelper.ToList<MyEnum>();
Gabriel
quelle
A Dictionaryist keine gute Idee: Wenn Sie eine haben , Enumwie enum E { A = 0, B = 0 }der Wert 0 2 mal hinzugefügt erzeugt ein ArgumentException(Sie denselben nicht hinzufügen können , Keyauf einem Dictionary2 oder mehrmals!).
Massimiliano Kraus
Warum eine Dictionary<,>von einer Methode namens zurückgeben ToList? Auch warum nicht zurückkehren Dictionary<T, string>?
Aluan Haddad
8

Fügen Sie public static IEnumerable<T> GetValues<T>()Ihrer Klasse eine Methode hinzu , wie:

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

Rufen Sie an und geben Sie Ihre Aufzählung weiter. Jetzt können Sie es durchlaufen mit foreach:

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

enumTypen werden als "Aufzählungstypen" bezeichnet, nicht weil sie Container sind, die Werte "auflisten" (was sie nicht sind), sondern weil sie durch Auflisten der möglichen Werte für eine Variable dieses Typs definiert werden.

(Tatsächlich ist das etwas komplizierter - Aufzählungstypen haben einen "zugrunde liegenden" Ganzzahltyp, was bedeutet, dass jeder Aufzählungswert einem Ganzzahlwert entspricht (dies ist normalerweise implizit, kann aber manuell angegeben werden). C # wurde entworfen auf eine Weise, dass Sie eine beliebige Ganzzahl dieses Typs in die Enum-Variable einfügen können, auch wenn es sich nicht um einen "benannten" Wert handelt.)

Die System.Enum.GetNames-Methode kann verwendet werden, um ein Array von Zeichenfolgen abzurufen, die die Namen der Enum-Werte sind, wie der Name schon sagt.

BEARBEITEN: Hätte stattdessen die System.Enum.GetValues- Methode vorschlagen sollen . Hoppla.

Emily Chen
quelle
2
Obwohl Ihre Antwort an sich richtig ist, geht sie nicht wirklich auf die ursprüngliche Frage des OP ein. Die GetNamesMethode gibt zwar ein String-Array zurück, aber das OP benötigt einen Enumerator für die Werte.
Silviu Preda
@ SilviuPreda: Bearbeitet. Es sollte GetValues ​​anstelle von GetNames sein.
Emily Chen
2

Ich habe viele Möglichkeiten ausprobiert und das Ergebnis aus diesem Code erhalten:

Verwenden Sie Folgendes, um eine Liste von int aus einer Aufzählung abzurufen. Es klappt!

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

Sie können sich auch direkt an die öffentlichen statischen Mitglieder der Aufzählung binden, indem Sie Reflection verwenden:

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

Wenn Sie haben:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Diese:

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

Wird ausgegeben:

Spades = 0
Hearts = 1
Clubs = 2
Diamonds = 3
rlv-dan
quelle
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());

Verwendungszweck:

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