Tego [Flags]
atrybutu należy używać, ilekroć element wyliczalny reprezentuje zbiór możliwych wartości, a nie pojedynczą wartość. Takie zbiory są często używane z operatorami bitowymi, na przykład:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Zauważ, że [Flags]
atrybut nie włącza tego sam w sobie - wszystko pozwala na ładną reprezentację za pomocą .ToString()
metody:
enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
...
var str1 = (Suits.Spades | Suits.Diamonds).ToString();
// "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
// "Spades, Diamonds"
Należy również zauważyć, że [Flags]
nie powoduje automatycznie, że wartości wyliczone są potęgami dwóch. Jeśli pominiesz wartości liczbowe, wyliczanie nie będzie działać, jak można oczekiwać w operacjach bitowych, ponieważ domyślnie wartości zaczynają się od 0 i zwiększają.
Niepoprawna deklaracja:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
Wartości, jeśli zostaną zadeklarowane w ten sposób, będą Żółte = 0, Zielone = 1, Czerwone = 2, Niebieskie = 3. To sprawi, że będzie bezużyteczne jako flagi.
Oto przykład poprawnej deklaracji:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
Aby pobrać różne wartości we właściwości, możesz to zrobić:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
lub przed .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Pod przykryciem
Działa to, ponieważ użyłeś potęgi dwóch w swoim wyliczeniu. Pod okładkami wartości wyliczenia wyglądają następująco w postaci binarnych zer i zer:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Podobnie, po ustawieniu właściwości Dozwolone kolory na Czerwony, Zielony i Niebieski za pomocą binarnego |
operatora bitowego OR , Dozwolone kolory wyglądają następująco:
myProperties.AllowedColors: 00001110
Więc kiedy odzyskujesz wartość, faktycznie wykonujesz bitowe AND &
dla wartości:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
Wartość Brak = 0
A jeśli chodzi o użycie 0
w wyliczeniu, cytowanie z MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Użyj None jako nazwy stałej wyliczonej z flagą, której wartość wynosi zero. Nie można użyć stałej wyliczonej None w bitowej operacji AND do przetestowania flagi, ponieważ wynik jest zawsze równy zero. Można jednak wykonać logiczne, a nie bitowe porównanie między wartością liczbową a stałą wyliczoną Brak, aby ustalić, czy ustawione są bity w wartości liczbowej.
Więcej informacji na temat atrybutu flagi i jego wykorzystania można znaleźć w msdn i projektowaniu flag w msdn