.net zählen - Wie zähle ich eine Aufzählung in C#auf?




wörter häufigkeiten (22)

Ich habe einige Erweiterungen für die einfache Verwendung von Enummen gemacht, vielleicht kann sie 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 Enum selbst muss mit dem FlagsAttribute

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

Wie können Sie eine enum in C # enum ?

Der folgende Code wird beispielsweise nicht kompiliert:

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

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

Und gibt den folgenden Kompilierungsfehler:

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

Bei dem Suit Schlüsselwort, dem zweiten, schlägt dies fehl.


Was zum Teufel werde ich meine zwei Pence einwerfen, indem ich einfach die obersten Antworten kombiniere, entsteht eine sehr einfache Erweiterung

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

Einfach sauber und durch @ Jeppe-Stig-Nielsens Kommentar schnell.


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

Der Autor verwendet eine doppelte for-Schleife, um ein Paar Enumeratoren zu durchlaufen (um ein volles Kartendeck 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 PlayingCard 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;
    }
}

Ich denke du kannst verwenden

Enum.GetNames(Suit)

Eine einfache und generische Methode, ein Enum in etwas umzuwandeln, das 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>();

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

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

Ich denke, das ist effizienter als andere Vorschläge, da GetValues() nicht jedes Mal aufgerufen wird, wenn Sie eine Schleife haben. Es ist auch prägnanter. Sie erhalten einen Fehler bei der Kompilierung und keine Laufzeitausnahme, wenn Suit keine enum .

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

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

Ich habe vage Gerüchte gehört, dass dies extrem langsam ist. Weiß jemand? - Orion Edwards 15. Oktober 08 um 01.31 Uhr 7

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

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

Das ist wenigstens ein bisschen schneller, ja?


Einige Versionen von .NET Framework unterstützen Enum.GetValues . Hier ist eine gute Lösung für Ideas 2.0: Enum.GetValues ​​in 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;
}

Wie bei jedem Code, der reflection , sollten Sie sicherstellen, dass er nur einmal ausgeführt wird und die Ergebnisse zwischengespeichert werden.


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

Warum verwendet niemand Cast<T> ?

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

Da gehst du IEnumerable<Suit> .


Wenn Sie die Geschwindigkeits- und Typüberprüfung zur Build- und Laufzeitzeit benötigen, ist diese Hilfsmethode besser als die Verwendung von LINQ, um jedes Element umzuwandeln:

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 IEnumerable<T> , aber das IEnumerable<T> Ihnen hier nichts.


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

Um meine Lösung hinzuzufügen, die im kompakten Framework (3.5) arbeitet und die Typüberprüfung zur Kompilierzeit unterstützt :

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

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

(Eigentlich ist das etwas komplizierter als das - Enum-Typen haben einen "zugrunde liegenden" Integer-Typ, was bedeutet, dass jeder Enum-Wert einem Integer-Wert entspricht (dies ist in der Regel implizit, kann aber manuell angegeben werden). C # wurde entworfen in einer 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 Strings abzurufen, die die Namen der Aufzählungswerte sind, wie der Name schon sagt.

BEARBEITEN: Sollte stattdessen die Methode System.Enum.GetValues vorgeschlagen haben. Hoppla.


Was ist, wenn Sie wissen, dass der Typ eine enum , aber Sie wissen nicht, welcher Typ zum Zeitpunkt des Kompilierens genau ist?

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 die Reflektion, um einen beliebigen Aufzählungstyp zu verwenden, und gibt eine 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));
}

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

(Die derzeit akzeptierte Antwort hat eine Besetzung, von der ich glaube, dass sie nicht benötigt wird (obwohl ich vielleicht falsch liege.)


Sie können auch mithilfe der Reflektion direkt an die öffentlichen statischen Mitglieder des Enums binden.

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

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

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

call und pass dein enum, jetzt kannst du es mit foreach durchlaufen

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

Ich glaube nicht, dass dies besser oder sogar gut ist und nur eine andere Lösung angibt.

Wenn die Aufzählungswerte streng zwischen 0 und n - 1 liegen, 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 die 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 keine strikte Aufzählung, sondern nur eine Schleife. Die zweite Methode ist jedoch viel schneller als jeder andere Ansatz ...


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

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

Der erste gibt Ihnen Werte in Form für ein Array von object und der zweite gibt Ihnen Werte in Form eines Arrays von String .

Verwenden Sie es in der foreach Schleife wie folgt:

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

Versionsgeschichte der C # -Sprache:

Dies sind die zum Zeitpunkt dieses Schreibens bekannten Versionen von C # :

  • C # 1.0 mit .NET 1.0 und VS2002 veröffentlicht (Januar 2002)
  • C # 1.2 (bizarr genug); veröffentlicht mit .NET 1.1 und VS2003 (April 2003). Erste Version, die Dispose für IEnumerator die IDisposable implementiert IDisposable . Ein paar andere kleine Funktionen.
  • C # 2.0 wurde mit .NET 2.0 und VS2005 (November 2005) veröffentlicht. Wichtige neue Funktionen: Generics, anonyme Methoden, nullfähige Typen, Iteratorblöcke
  • C # 3.0 wurde mit .NET 3.5 und VS2008 (November 2007) veröffentlicht. Wichtige neue Funktionen: Lambda-Ausdrücke, Erweiterungsmethoden, Ausdrucksbäume, anonyme Typen, implizite Typisierung ( var ), Abfrageausdrücke
  • C # 4.0 wurde mit .NET 4 und VS2010 (April 2010) veröffentlicht. Wichtige neue Funktionen: späte Bindung ( dynamic ), generische Varianz für Delegaten und Schnittstellen, mehr COM-Unterstützung, benannte Argumente, Tupel-Datentyp und optionale Parameter
  • C # 5.0 wurde mit .NET 4.5 und VS2012 (August 2012) veröffentlicht. Hauptfunktionen: asynchrone Programmierung, Attribute für Anruferinformationen. Breaking change: Schleifenvariable schließen .
  • C # 6.0 wurde mit .NET 4.6 und VS2015 (Juli 2015) veröffentlicht. Umgesetzt von Roslyn . Features : Initialisierer für automatisch implementierte Eigenschaften, Direktive zum Importieren statischer Member, Ausnahmefilter, Elementinitialisierer, await in catch und zum finally Add Methoden in Collection-Initialisierern.
  • C # 7.0 mit .NET 4.7 und VS2017 (März 2017) veröffentlicht. Wichtige neue Funktionen : tuples , Ref-Locals und Ref-Return , Musterabgleich (einschließlich musterbasierter switch-Anweisungen), Inline- out Parameterdeklarationen , lokale Funktionen , Binärliterale, Zifferntrennzeichen . und willkürliche async kehrt zurück .
  • C # 7.1 mit VS2017 v15.3 (August 2017) veröffentlicht. Neue Funktionen: Async-Main , Rückschluss auf den Namen des Tupel-Mitglieds , Standardausdruck , Musterabgleich mit Generika .
  • C # 7.2 mit VS2017 v15.5 (November 2017) veröffentlicht Neue Funktionen: Privater geschützter Zugriffsmodifikator , Span <T>, aka Interieur Pointer, aka Stackonly struct , alles andere .
  • C # 7.3 wurde mit VS2017 v15.7 (Mai 2018) veröffentlicht. Neue Funktionen: Enum, Delegate und nicht unmanaged generische Typeinschränkungen . Umwidmung. Unsichere Verbesserungen: stackalloc Initialisierung, nicht gepinnte indizierte fixed Puffer, benutzerdefinierte fixed Anweisungen. Verbesserte Überladungsauflösung. Ausdrucksvariablen in Initialisierern und Abfragen. == und != für Tupel definiert. Die Sicherungsfelder der Auto-Eigenschaften können jetzt von Attributen anvisiert werden.
  • C # 8.0 derzeit in der Vorschau. Erwartete neue Funktionen : Nicht-nullfähige Referenztypen , IAsyncEnumerable<T> -Unterstützung, Bereiche und Standardschnittstellenmethoden.

Als Antwort auf die Frage des OP:

Was sind die korrekten Versionsnummern für C #? Was kam wann heraus? Warum kann ich keine Antworten zu C # 3.5 finden?

Es gibt kein C # 3.5 - die Ursache der Verwirrung ist, dass das C # 3.0 in .NET 3.5 vorhanden ist. Die Sprache und das Framework werden jedoch unabhängig voneinander versioniert - ebenso wie die CLR, die sich in Version 2.0 für .NET 2.0 bis 3.5 befindet. .NET 4 führt CLR 4.0 ein, ungeachtet der Service Packs. Die CLR in .NET 4.5 weist verschiedene Verbesserungen auf, die Versionierung ist jedoch unklar: An einigen Stellen wird sie als CLR 4.5 bezeichnet ( diese MSDN-Seite wird beispielsweise so verwendet), aber die Eigenschaft Environment.Version bleibt erhalten meldet 4.0.xxx.

Ausführlichere Informationen zur Beziehung zwischen der Sprach-, Laufzeit- und Framework-Version finden Sie auf der Website von C # in Depth . Dies enthält Informationen dazu, welche Features von C # 3.0 Sie beim Targeting von .NET 2.0 verwenden können. (Wenn jemand den gesamten Inhalt in diese Wiki-Antwort einbringen möchte, kann er dies gerne tun.)

Seit dem 3. Mai 2017 hat das C # -Sprachenteam eine Historie der C # -Versionen und -Funktionen für ihr Github-Repo erstellt: In C # -Programmversionen hinzugefügte Funktionen . Es gibt auch eine Seite, die kommende und kürzlich implementierte Sprachfunktionen aufzeichnet .





c# .net enums enumeration