Что означает атрибут Enum [Flags] в C #?

Для тех, кто ищет решение Java для этого, если вы используете mongojack , это очень просто:

collection.find(DBQuery.is("user", new DBRef(user.getId(), User.class)));

Где коллекция является JacksonDBCollection.

1326
задан Vogel612 11 October 2014 в 10:48
поделиться

7 ответов

Эти [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, Green = 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 на Красного, Green и Синее использование двоичного битового "ИЛИ" | оператор, AllowedColors похож на это:

myProperties.AllowedColors: 00001110

Поэтому при получении значения Вы на самом деле выполняете поразрядно И & на значениях:

myProperties.AllowedColors: 00001110
             MyColor.Green: 00000010
             -----------------------
                            00000010 // Hey, this is the same as MyColor.Green!

Ни один = 0 значений

И относительно использования [1 116] в Вашем перечислении, заключающем в кавычки из MSDN:

[Flags]
public enum MyColors
{
    None = 0,
    ....
}

Использование Ни один как название перечислимой константы флага, значение которой является нулем. Вы не можете использовать Ни один перечислимая константа в поразрядной операции И для тестирования на флаг, потому что результатом всегда является нуль. Однако можно выполнить логическое, не поразрядное, сравнение между числовым значением и Ни одним перечислимая константа, чтобы определить, установлены ли какие-либо биты в числовом значении.

можно найти больше информации об атрибуте флагов и его использовании в [1 117] msdn и флаги разработки в msdn

2011
ответ дан Matt Jenkins 11 October 2014 в 10:48
поделиться

Добавить Mode.Write:

Mode = Mode | Mode.Write;
17
ответ дан shA.t 11 October 2014 в 10:48
поделиться

Посмотрите следующее для примера, который показывает объявление и потенциальное использование:

namespace Flags
{
    class Program
    {
        [Flags]
        public enum MyFlags : short
        {
            Foo = 0x1,
            Bar = 0x2,
            Baz = 0x4
        }

        static void Main(string[] args)
        {
            MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;

            if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
            {
                Console.WriteLine("Item has Foo flag set");
            }
        }
    }
}
48
ответ дан Jaider 11 October 2014 в 10:48
поделиться

Я спрошенный недавно о чем-то подобном.

при использовании флагов можно добавить дополнительный метод к перечислениям для создания проверки содержавших флагов легче (см. сообщение для детали)

Это позволяет Вам делать:

[Flags]
public enum PossibleOptions : byte
{
    None = 0,
    OptionOne = 1,
    OptionTwo = 2,
    OptionThree = 4,
    OptionFour = 8,

    //combinations can be in the enum too
    OptionOneAndTwo = OptionOne | OptionTwo,
    OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
    ...
}

Тогда можно сделать:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree 

if( opt.IsSet( PossibleOptions.OptionOne ) ) {
    //optionOne is one of those set
}

я нахожу это легче читать, чем большинство способов проверить включенные флаги.

34
ответ дан Community 11 October 2014 в 10:48
поделиться

@Nidonocu

Для добавления другого флага к существующему набору значений используйте ИЛИ оператор присваивания.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));
22
ответ дан steve_c 11 October 2014 в 10:48
поделиться

Флаги позволяют Вам использовать bitmasking в своем перечислении. Это позволяет Вам комбинировать перечислимые величины при сохранении, которые определяются.

[Flags]
public enum DashboardItemPresentationProperties : long
{
    None = 0,
    HideCollapse = 1,
    HideDelete = 2,
    HideEdit = 4,
    HideOpenInNewWindow = 8,
    HideResetSource = 16,
    HideMenu = 32
}
11
ответ дан Markus Safar 11 October 2014 в 10:48
поделиться

Можно также сделать это

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3
}

, я нахожу смещение бита легче, чем ввод 4,8,16,32 и так далее. Это не оказывает влияния на Ваш код, потому что это все сделано во время компиляции

745
ответ дан Orion Edwards 11 October 2014 в 10:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: