Атрибут [Flags]
должен использоваться всякий раз, когда перечисляемое представляет коллекцию возможных значений, а не одно значение. Такие коллекции часто используются с побитовыми операторами, например:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Обратите внимание, что атрибут [Flags]
не сам по себе это разрешает - все, что он делает, это разрешает хорошее представление методом .ToString()
:
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"
Также важно отметить, что [Flags]
не автоматически делает значения перечисления степенями двух. Если вы опустите числовые значения, перечисление не будет работать так, как можно ожидать в побитовых операциях, потому что по умолчанию значения начинаются с 0 и увеличиваются.
Неверное объявление:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
Значения, если они будут объявлены таким образом, будут Yellow = 0, Green = 1, Red = 2, Blue = 3. Это сделает их бесполезными в качестве флагов.
Вот пример правильного объявления:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
Чтобы получить различные значения в вашей собственности, можно сделать это:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
или до .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Под одеялом
Это работает, потому что вы использовали степени двух в своем перечислении. Под обложками ваши значения перечисления выглядят так в двоичных единицах и нулях:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Аналогично, после того, как вы установили для своего свойства AllowedColors значение Red, Green и Blue с использованием двоичного оператора ИЛИ |
, AllowedColors выглядит следующим образом:
myProperties.AllowedColors: 00001110
Таким образом, когда вы получаете значение, которое вы фактически выполняете побитовое И &
для значений:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
Значение None = 0
А что касается использования 0
в вашем перечислении, цитата из MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Использовать None в качестве имени перечисляемой константы флага, значение которой равно нулю. Вы не можете использовать перечисляемую константу None в побитовой операции AND для проверки флага, поскольку результат всегда равен нулю. Однако вы можете выполнить логическое, а не побитовое сравнение числового значения и None. константа перечисления, чтобы определить, установлены ли какие-либо биты в числовом значении.
Вы можете найти больше информации об атрибуте flags и его использовании в msdn и , проектируя флаги в msdn