Атрибут [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
}
Значения, если они объявлены таким образом, будут: Желтый = 0, Зеленый = 1, Красный = 2, Синий = 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 с помощью двоичного побитового оператора OR |
, 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 для проверки наличия флага, потому что результат всегда равен нулю. Однако вы можете выполнить логическое, а не побитовое сравнение числового значения и Отсутствует перечислимая константа, определяющая, установлены ли какие-либо биты в числовом значении.
Дополнительную информацию об атрибуте flags и его использовании можно найти на странице msdn и разработка флагов в msdn
person
andynil
schedule
12.08.2008
CatAndDog = Cat | Dog
(логическое ИЛИ вместо условного), я полагаю? - person DdW   schedule 12.09.2016