Атрибут flags должен использоваться всякий раз, когда перечисляемый представляет собой набор флагов, а не одно значение. Такие коллекции обычно обрабатываются с помощью побитовых операторов, например:
myProperties.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,
Green,
Red,
Blue
}
Значения, объявленные таким образом, будут желтыми = 0, зеленым = 1, красным = 2, синим = 3. Это сделает его бесполезно для использования в качестве флагов.
Вот пример правильного объявления:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
Чтобы получить отдельные значения в вашем свойстве, вы можете сделать это:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow has been set...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green has been set...
}
или в .NET 4 и более поздних версиях:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow has been set...
}
Под обложками
Это работает, потому что вы ранее использовали полномочия двух в вашем перечислении. Под обложками ваши значения перечисления выглядят следующим образом (представлены как байты, которые имеют 8 бит, которые могут быть 1 или 0)
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Аналогично, после того, как вы установили свое свойство AllowedColors к красному, зеленому и синему (какие значения, где OR'ed трубой |), AllowedColors выглядит так
myProperties.AllowedColors: 00001110
Поэтому, когда вы извлекаете значение, которое вы на самом деле побитовое значение AND_ing значений
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, указанную в побитовой операции И, чтобы проверить флаг, потому что результат всегда равен нулю. Однако вы можете выполнить логическое, а не поразрядное сравнение между числовым значением и перечислимой константой None, чтобы определить, установлены ли какие-либо биты в числовом значении.
blockquote>
Дополнительную информацию об атрибуте flags и его использовании можно найти в msdn и флажках проектирования в msdn