Wenn ich eine Variable habe, die eine Flags-Aufzählung enthält, kann ich dann irgendwie über die Bitwerte in dieser bestimmten Variablen iterieren? Oder muss ich Enum.GetValues verwenden, um die gesamte Enumeration zu durchlaufen und zu überprüfen, welche festgelegt sind?
c#
enums
enum-flags
Olivier Rogier
quelle
quelle
Antworten:
quelle
HasFlag
ab .NET 4 verfügbar ist.Enum.GetValues(input.GetType()).Cast<Enum>().Where(input.HasFlag);
myEnum.GetFLags()
static IEnumerable<Enum> GetFlags(this Enum input)
Hier ist eine Linq-Lösung für das Problem.
quelle
.Where(v => !Equals((int)(object)v, 0) && e.HasFlag(v));
Sie, wenn Sie einen Nullwert zur Darstellung habenNone
Soweit ich weiß, gibt es keine integrierten Methoden, um jede Komponente abzurufen. Aber hier ist eine Möglichkeit, wie Sie sie erhalten können:
Ich habe die
Enum
internen Funktionen angepasst , um die Zeichenfolge zu generieren und stattdessen die Flags zurückzugeben. Sie können den Code im Reflektor betrachten und sollten mehr oder weniger gleichwertig sein. Funktioniert gut für allgemeine Anwendungsfälle, in denen Werte mehrere Bits enthalten.Die Erweiterungsmethode
GetIndividualFlags()
ruft alle einzelnen Flags für einen Typ ab. Werte, die mehrere Bits enthalten, werden also weggelassen.quelle
Bar
,Baz
undBoo
nicht nurBoo
.Boo
(der Wert, der mit zurückgegeben wirdToString()
). Ich habe es so angepasst, dass nur einzelne Flags zugelassen werden. Also in meinem Beispiel können Sie bekommenBar
undBaz
stattBoo
.Als ich einige Jahre später mit etwas mehr Erfahrung darauf zurückkomme, ist meine ultimative Antwort nur für Einzelbitwerte, die vom niedrigsten zum höchsten Bit übergehen, eine leichte Variante von Jeff Mercados innerer Routine:
Es scheint zu funktionieren, und trotz meiner Einwände vor einigen Jahren verwende ich hier HasFlag, da es weitaus besser lesbar ist als bitweise Vergleiche und der Geschwindigkeitsunterschied für alles, was ich tun werde, unbedeutend ist. (Es ist durchaus möglich, dass sie seitdem die Geschwindigkeit von HasFlags verbessert haben, soweit ich weiß ... ich habe es nicht getestet.)
quelle
yield return bits;
?Wenn Sie die Methode von @ Greg verlassen, aber eine neue Funktion aus C # 7.3 hinzufügen, lautet die
Enum
Einschränkung:Die neue Einschränkung ermöglicht es, dass dies eine Erweiterungsmethode ist, ohne dass sie durchgearbeitet werden muss
(int)(object)e
, und ich kann dieHasFlag
Methode verwenden und direkt vonT
aus umwandelnvalue
.C # 7.3 fügte auch Einschränkungen für Verzögerungen und hinzu
unmanaged
.quelle
flags
Parameter auch vom generischen TypT
ist, andernfalls müssten Sie den Aufzählungstyp bei jedem Aufruf explizit angeben.+1 für die Antwort von @ RobinHood70. Ich fand, dass eine generische Version der Methode für mich praktisch war.
EDIT Und +1 für @AustinWBryan, um C # 7.3 in den Lösungsraum zu bringen.
quelle
Sie müssen nicht alle Werte iterieren. Überprüfen Sie einfach Ihre spezifischen Flags wie folgt:
oder (wie pstrjds in den Kommentaren sagte) Sie können überprüfen, ob Sie es verwenden, wie:
quelle
Ich habe meinen Ansatz geändert, anstatt den Eingabeparameter der Methode als
enum
Typ einzugeben , habe ich ihn als Array vomenum
Typ (MyEnum[] myEnums
) eingegeben. Auf diese Weise durchlaufe ich das Array einfach mit einer switch-Anweisung innerhalb der Schleife.quelle
War mit den obigen Antworten nicht zufrieden, obwohl sie der Anfang waren.
Nachdem Sie hier einige verschiedene Quellen zusammengesetzt haben:
Vorheriges Poster im SO QnA-
Code-Projekt Enum Flags dieses Threads Check Post
Great Enum <T> Utility
Ich habe das erstellt, also lass mich wissen, was du denkst.
Parameter ::
bool checkZero
Weist es an,0
als Flag-Wert zuzulassen . Standardmäßig wirdinput = 0
leer zurückgegeben.bool checkFlags
: weist es an zu prüfen, ob dasEnum
mit dem[Flags]
Attribut dekoriert ist .PS. Ich habe momentan keine Zeit, die
checkCombinators = false
Alge herauszufinden, die sie dazu zwingt, alle Enum-Werte zu ignorieren, die Kombinationen von Bits sind.Hierbei wird die hier gefundene Helper Class Enum <T> verwendet, die ich aktualisiert habe, um sie zu verwenden
yield return
fürGetValues
:Zum Schluss noch ein Beispiel für die Verwendung:
quelle
Aufbauend auf Gregs obiger Antwort wird auch der Fall behandelt, in dem Sie einen Wert 0 in Ihrer Aufzählung haben, z. B. None = 0. In diesem Fall sollte dieser Wert nicht durchlaufen werden.
Würde jemand wissen, wie man dies noch weiter verbessern kann, damit es den Fall behandeln kann, in dem alle Flags in der Aufzählung auf eine super intelligente Weise gesetzt sind, die alle zugrunde liegenden Aufzählungstypen und den Fall von All = ~ 0 und All = EnumValue1 | behandeln kann EnumValue2 | EnumValue3 | ...
quelle
Sie können einen Iterator aus der Aufzählung verwenden. Ausgehend vom MSDN-Code:
Es ist nicht getestet. Wenn ich also einen Fehler gemacht habe, können Sie mich gerne anrufen. (Offensichtlich ist es kein Wiedereintritt.) Sie müssten den Wert vorher zuweisen oder ihn in eine andere Funktion aufteilen, die enum.dayflag und enum.days verwendet. Möglicherweise können Sie mit der Gliederung irgendwohin gehen.
quelle
Es könnte auch der folgende Code sein:
Es geht nur dann hinein, wenn der Aufzählungswert im Wert enthalten ist
quelle
Alle Antworten funktionieren gut mit einfachen Flags. Wenn Sie Flags kombinieren, werden Sie wahrscheinlich auf Probleme stoßen.
Möglicherweise muss eine Prüfung hinzugefügt werden, um zu testen, ob der Enum-Wert selbst eine Kombination ist. Sie würden wahrscheinlich etwas brauchen, wie es hier von Henk van Boeijen gepostet wurde , um Ihren Bedarf zu decken (Sie müssen ein wenig nach unten scrollen)
quelle
Erweiterungsmethode unter Verwendung der neuen Enum-Einschränkung und der neuen Generika, um das Casting zu verhindern:
quelle
Sie können dies direkt tun, indem Sie in int konvertieren, aber Sie verlieren die Typprüfung. Ich denke, der beste Weg ist, etwas Ähnliches wie meinen Vorschlag zu verwenden. Es behält den richtigen Typ den ganzen Weg. Keine Konvertierung erforderlich. Es ist nicht perfekt, weil das Boxen die Leistung ein wenig beeinträchtigt.
Nicht perfekt (Boxen), aber es macht den Job ohne Vorwarnung ...
Verwendung:
quelle