Von Zeit zu Zeit sehe ich eine Aufzählung wie die folgende:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
Ich verstehe nicht genau, was das [Flags]
Attribut bewirkt.
Hat jemand eine gute Erklärung oder ein Beispiel, das er posten könnte?
CatAndDog = Cat | Dog
(das logische ODER anstelle des Bedingten), nehme ich an?Antworten:
Das
[Flags]
Attribut sollte immer dann verwendet werden, wenn die Aufzählung eine Sammlung möglicher Werte anstelle eines einzelnen Werts darstellt. Solche Sammlungen werden häufig mit bitweisen Operatoren verwendet, zum Beispiel:Beachten Sie, dass das
[Flags]
Attribut dies nicht selbst aktiviert - alles, was es tut, ist eine schöne Darstellung durch die.ToString()
Methode:Es ist auch wichtig zu beachten, dass die Aufzählungswerte
[Flags]
nicht automatisch zu Zweierpotenzen werden. Wenn Sie die numerischen Werte weglassen, funktioniert die Aufzählung nicht wie bei bitweisen Operationen zu erwarten, da die Werte standardmäßig mit 0 beginnen und inkrementieren.Falsche Erklärung:
Wenn die Werte auf diese Weise deklariert werden, sind sie Gelb = 0, Grün = 1, Rot = 2, Blau = 3. Dies macht sie als Flags unbrauchbar.
Hier ist ein Beispiel für eine korrekte Deklaration:
Um die unterschiedlichen Werte in Ihrer Eigenschaft abzurufen, haben Sie folgende Möglichkeiten:
oder vor .NET 4:
Unter der Decke
Dies funktioniert, weil Sie in Ihrer Aufzählung Zweierpotenzen verwendet haben. Unter der Decke sehen Ihre Aufzählungswerte in binären Einsen und Nullen folgendermaßen aus:
Nachdem Sie Ihre Eigenschaft AllowedColors mit dem binären bitweisen ODER-
|
Operator auf Rot, Grün und Blau festgelegt haben, sieht AllowedColors folgendermaßen aus:Wenn Sie also den Wert abrufen, führen Sie tatsächlich bitweise UND
&
für die Werte aus:Der Wert None = 0
Und in Bezug auf die Verwendung von
0
in Ihrer Aufzählung, zitiert aus MSDN:Weitere Informationen zum Flags-Attribut und seiner Verwendung finden Sie unter msdn und zum Entwerfen von Flags unter msdn
quelle
ToString
Umsetzung Ihrer ENUM nutzt Flags, und so funktioniertEnum.IsDefined
,Enum.Parse
usw. Versuchen Flaggen und Blick auf das Ergebnis von MyColor.Yellow entfernen | MyColor.Red; ohne es bekommst du "5", mit Flags bekommst du "Yellow, Red". Einige andere Teile des Frameworks verwenden ebenfalls [Flags] (z. B. XML-Serialisierung).myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
. Sie können tun:myProperties.AllowedColors = myProperties.AllowedColors ^ MyColor.Blue //myProperties.AllowedColors == MyColor.Red | Mycolor.Green
Sie können dies auch tun
Ich finde das Bit-Shifting einfacher als das Eingeben von 4,8,16,32 und so weiter. Dies hat keine Auswirkungen auf Ihren Code, da alles zur Kompilierungszeit ausgeführt wird
quelle
Third = Second << 1
Third = 1 << 2
1 << 31 == -2147483648
,1 << 32 == 1
,1 << 33 == 2
, und so weiter. Wenn Sie dagegenThirtySecond = 2147483648
für eine Aufzählung vom Typ int sagen , gibt der Compiler einen Fehler aus.Wenn Sie die Antworten https://stackoverflow.com/a/8462/1037948 (Deklaration über Bitverschiebung) und https://stackoverflow.com/a/9117/1037948 (Verwendung von Kombinationen in der Deklaration) kombinieren, können Sie frühere Werte eher bitverschieben als mit Zahlen. Nicht unbedingt zu empfehlen, aber nur darauf hinzuweisen, dass Sie es können.
Eher, als:
Sie können deklarieren
Bestätigung mit LinqPad:
Ergebnisse in:
quelle
Im Folgenden finden Sie ein Beispiel, das die Deklaration und die mögliche Verwendung zeigt:
quelle
In Erweiterung zur akzeptierten Antwort können in C # 7 die Enum-Flags mit binären Literalen geschrieben werden:
Ich denke, diese Darstellung macht deutlich, wie die Flaggen unter der Decke funktionieren .
quelle
0b_0100
Ich habe kürzlich nach etwas Ähnlichem gefragt .
Wenn Sie Flags verwenden, können Sie Enums eine Erweiterungsmethode hinzufügen, um das Überprüfen der enthaltenen Flags zu vereinfachen (siehe Beitrag für Details).
Dies ermöglicht Ihnen Folgendes:
Dann können Sie tun:
Ich finde das leichter zu lesen als die meisten Möglichkeiten, die enthaltenen Flags zu überprüfen.
quelle
HasFlag
Aufzählung zu Aufzählungen hinzu, so dass Sieopt.HasFlag( PossibleOptions.OptionOne )
ohne Ihre eigenen Erweiterungen schreiben müssenHasFlag
ist viel langsamer als tun bitweise Operationen.@ Nidonocu
Verwenden Sie den OR-Zuweisungsoperator, um einem vorhandenen Wertesatz ein weiteres Flag hinzuzufügen.
quelle
Wenn ich mit Flags arbeite, deklariere ich oft zusätzliche Keine und Alle Elemente. Diese sind hilfreich, um zu überprüfen, ob alle Flags gesetzt sind oder kein Flag gesetzt ist.
Verwendungszweck:
Update 2019-10:
Seit C # 7.0 können Sie binäre Literale verwenden, die wahrscheinlich intuitiver zu lesen sind:
quelle
Hinzufügen
Mode.Write
:quelle
Es gibt etwas allzu ausführliche mir über das
if ((x & y) == y)...
Konstrukt, vor allem , wennx
ANDy
sind beide Verbindung Sätze von Flaggen und Sie wollen nur wissen , ob es irgendeine Überlappung.In diesem Fall müssen Sie nur wissen, ob nach der Bitmaske ein Wert ungleich Null [1] vorliegt .
Aufbauend auf @ andnils Setup ...
quelle
enum
, müssen wir prüfen, ob!= 0
.Mit Flags können Sie Bitmasking in Ihrer Aufzählung verwenden. Auf diese Weise können Sie Aufzählungswerte kombinieren und gleichzeitig die angegebenen Werte beibehalten.
quelle
Entschuldigung, wenn jemand dieses Szenario bereits bemerkt hat. Ein perfektes Beispiel für Flaggen, die wir in der Reflexion sehen können. Ja Bindungsflaggen ENUM. https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=netframework-4.8
Verwendungszweck
quelle