L' [Flags]
attributo dovrebbe essere usato ogni volta che l'enumerabile rappresenta una raccolta di valori possibili, anziché un singolo valore. Tali raccolte vengono spesso utilizzate con operatori bit a bit, ad esempio:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Nota che l' [Flags]
attributo non lo abilita da solo - tutto ciò che fa è consentire una buona rappresentazione con il .ToString()
metodo:
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"
È anche importante notare che [Flags]
non rende automaticamente i valori di enum potenze di due. Se si omettono i valori numerici, l'enum non funzionerà come ci si aspetterebbe in operazioni bit a bit, perché per impostazione predefinita i valori iniziano con 0 e incrementano.
Dichiarazione errata:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
I valori, se dichiarati in questo modo, saranno Giallo = 0, Verde = 1, Rosso = 2, Blu = 3. Questo lo renderà inutile come flag.
Ecco un esempio di una dichiarazione corretta:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
Per recuperare i valori distinti nella tua proprietà, puoi farlo:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
o prima di .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Sotto le coperte
Questo funziona perché hai usato poteri di due nella tua enumerazione. Sotto le copertine, i valori di enumerazione si presentano così in binari e zeri:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Allo stesso modo, dopo aver impostato la proprietà AllowColors su Red, Green e Blue utilizzando l' |
operatore binario OR bit a bit , AllowColors è simile al seguente:
myProperties.AllowedColors: 00001110
Quindi, quando recuperi il valore, stai effettivamente eseguendo AND bit a bit &
sui valori:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
Il valore Nessuno = 0
E per quanto riguarda l'uso di 0
nella tua enumerazione, citando da MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Utilizzare None come nome della costante elencata flag il cui valore è zero. Non è possibile utilizzare la costante enumerata None in un'operazione AND bit a bit per verificare un flag perché il risultato è sempre zero. Tuttavia, è possibile eseguire un confronto logico, non a livello di bit, tra il valore numerico e la costante enumerata Nessuno per determinare se sono impostati eventuali bit nel valore numerico.
Puoi trovare maggiori informazioni sull'attributo flags e sul suo utilizzo su msdn e progettare flag su msdn