O [Flags]
atributo deve ser usado sempre que o enumerável representar uma coleção de valores possíveis, em vez de um único valor. Essas coleções são frequentemente usadas com operadores bit a bit, por exemplo:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Observe que o [Flags]
atributo não permite isso por si só - tudo o que faz é permitir uma boa representação pelo .ToString()
método:
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"
Também é importante notar que [Flags]
não fazer automaticamente os valores ENUM potências de dois. Se você omitir os valores numéricos, a enumeração não funcionará como seria de esperar em operações bit a bit, porque, por padrão, os valores começam com 0 e incrementam.
Declaração incorreta:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
Os valores, se declarados dessa maneira, serão Amarelo = 0, Verde = 1, Vermelho = 2, Azul = 3. Isso o tornará inútil como sinalizadores.
Aqui está um exemplo de uma declaração correta:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
Para recuperar os valores distintos em sua propriedade, é possível fazer o seguinte:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
ou anterior ao .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Debaixo das cobertas
Isso funciona porque você usou poderes de dois em sua enumeração. Nos bastidores, seus valores de enumeração são assim em zeros e binários:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Da mesma forma, depois de definir sua propriedade AllowedColors como Vermelho, Verde e Azul usando o |
operador binário OR bit a bit , AllowedColors fica assim:
myProperties.AllowedColors: 00001110
Portanto, quando você recupera o valor, está realmente executando AND bit a bit &
nos valores:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
O valor None = 0
E sobre o uso de 0
na sua enumeração, citando o MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Use None como o nome da constante enumerada do sinalizador cujo valor é zero. Você não pode usar a constante enumerada None em uma operação AND bit a bit para testar um sinalizador porque o resultado é sempre zero. No entanto, você pode executar uma comparação lógica, não um bit a bit, entre o valor numérico e a constante enumerada None para determinar se algum bit no valor numérico está definido.
Você pode encontrar mais informações sobre o atributo flags e seu uso no msdn e sobre o design de flags no msdn