it-swarm.com.de

Wie zähle ich eine Enumeration in C # auf?

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

Z.B. Der folgende Code wird nicht kompiliert:

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

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

Und gibt den folgenden Kompilierungsfehler aus:

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

Das zweite Schlüsselwort, Suit, schlägt fehl.

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

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

4363
jop

Mir scheint, Sie möchten wirklich die Namen der einzelnen Aufzählungen und nicht die Werte ausdrucken. In diesem Fall scheint Enum.GetNames() 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 Methode, um die Werte einer Aufzählung aufzulisten. Sie sollten dies stattdessen tun.

Ich würde stattdessen Enum.GetValues(typeof(Suit)) 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());
    }
}
652
Haacked

Ich habe einige Erweiterungen für die einfache Verwendung von Enum gemacht, vielleicht kann es jemand verwenden ...

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 werden

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

Einige Versionen von .NET Framework unterstützen Enum.GetValues nicht. Hier ist eine gute Umgehung 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 Reflektion beinhaltet, sollten Sie sicherstellen, dass er nur einmal ausgeführt wird und die Ergebnisse zwischengespeichert werden.

170
Ekevoo

Warum benutzt niemand Cast<T>?

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

Da gehts IEnumerable<Suit>.

104
sircodesalot

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

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

EnumLoop hat diese vollständig 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]);
        }
    }
}
93
James

In Silverlight wird Enum.GetValues() nicht angezeigt.

Original Blog Post 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();
    }
}
74
Aubrey Taylor

Nur um meine Lösung hinzuzufügen, die in einem kompakten Framework (3.5) funktioniert und die Typprüfung unterstützt zur Kompilierungszeit:

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 die T valueType = new T() loswird, würde ich mich über eine Lösung freuen.

Ein Anruf würde so aussehen:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
56
Mallox

Ich denke, Sie können verwenden

Enum.GetNames(Suit)
51
Tom Carr
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
49
Joshua Drake
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

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

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

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

Das geht wenigstens ein bisschen schneller, ja?

48

Drei Wege:

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

Ich bin mir nicht sicher, warum GetEnumValues in der Typinstanz eingeführt wurde. Es ist für mich überhaupt nicht gut lesbar.


Eine Helferklasse wie Enum<T> zu haben, ist für mich am lesbarsten und einprägsamsten:

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 gehe davon aus, dass dies überhaupt kein Problem darstellt

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

Was zum Teufel werde ich meine zwei Pence reinwerfen, indem ich einfach die Top-Antworten kombiniere, die ich durch eine sehr einfache Erweiterung zusammenstelle

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

Sauber einfach und durch @ Jeppe-Stig-Nielsens Kommentar schnell.

26
Darkside

Ich benutze ToString (), teile und parse 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);
}
22

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

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

Der erste gibt Ihnen Werte in Form eines Arrays von object und der zweite Werte in Form eines Arrays von String.

Verwenden Sie es in der foreach-Schleife wie folgt:

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

Wenn Sie eine Geschwindigkeits- und Typüberprüfung zur Erstellungs- und Laufzeit benötigen, ist diese Hilfsmethode besser als die Verwendung von LINQ zum Umwandeln der einzelnen Elemente:

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 kannst du IEnumerable<T> zurückgeben, aber das bringt dir hier nichts.

16
dmihailescu

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

Wenn die Enum-Werte streng zwischen 0 und n - 1 liegen, ist dies 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 das letzte Element der Aufzählung angeben können, gilt Folgendes:

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

aber das ist nicht streng aufgezählt, nur eine Schleife. Die zweite Methode ist jedoch viel schneller als jeder andere Ansatz ...

16
nawfal

hier ist ein funktionierendes Beispiel für das 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()
      };
13
jhilden
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

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

10
matt burns

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

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 sind Suit und Value 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 PlayingCard ist ein Kartenobjekt mit einem definierten Suit und Value:

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

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

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

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

Was ist, wenn Sie wissen, dass der Typ ein enum ist, aber Sie 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 getListOfEnum verwendet Reflection, um einen beliebigen Aufzählungstyp zu verwenden, und gibt ein IEnumerable aller 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));
}
8
Slappywag

Eine einfache und generische Möglichkeit, eine Aufzählung in etwas zu konvertieren, 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>();
8
Gabriel

Fügen Sie Ihrer Klasse beispielsweise die Methode public static IEnumerable<T> GetValues<T>() hinzu

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

rufen Sie an und übergeben Sie Ihre Aufzählung. Jetzt können Sie sie mit foreach durchlaufen.

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

enum -Typen werden als "Aufzählungstypen" bezeichnet, nicht weil sie Container sind, die Werte "auflisten" (was sie nicht sind), sondern weil sie durch Aufzählen der mögliche Werte für eine Variable dieses Typs.

(Tatsächlich ist das etwas komplizierter - Aufzählungstypen haben einen "zugrunde liegenden" Integer-Typ, was bedeutet, dass jeder Aufzählungswert einem Integer-Wert 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 vermuten lässt.

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

1
Emily Chen

Sie können sich auch direkt mit Reflection an die öffentlichen statischen Mitglieder der Enumeration binden:

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