[C#] C #에서 [Flags] 열거 형 속성의 의미는 무엇입니까?

때때로 나는 다음과 같은 열거 형을 봅니다.

[Flags]
public enum Options
{
    None    = 0,
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
    Option4 = 8
}

[Flags]속성이 정확히 무엇인지 이해 하지 못합니다.

누구나 좋은 설명이나 예를 게시 할 수 있습니까?



답변

[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...
}    

덮개 아래

열거 형에 2의 거듭 제곱을 사용했기 때문에 작동합니다. 표지 아래에서 열거 형 값은 이진수 1과 0으로 표시됩니다.

 Yellow: 00000001
 Green:  00000010
 Red:    00000100
 Blue:   00001000

마찬가지로 이진 비트 OR 연산자를 사용하여 AllowedColors 속성 을 빨강, 녹색 및 파랑으로 설정하면 AllowedColors 는 다음과 같습니다.|

myProperties.AllowedColors: 00001110

따라서 값을 검색하면 실제로 &값에 대해 비트 단위 AND 를 수행 합니다.

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

None = 0 값

그리고 0MSDN에서 인용하여 열거에서 사용하는 것과 관련하여 :

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

값이 0 인 플래그 열거 상수의 이름으로 None을 사용하십시오. 결과가 항상 0이므로 비트 AND 연산에서 None 열거 상수를 사용하여 플래그를 테스트 할 수 없습니다. 그러나 숫자 값의 비트가 설정되어 있는지 여부를 확인하기 위해 숫자 값과 없음 열거 상수 사이의 비트 단위가 아닌 논리적 비교를 수행 할 수 있습니다.

당신은 더 플래그 특성에 대한 정보와에서의 사용을 찾을 수 MSDNMSDN에서 설계 플래그


답변

당신은 또한 이것을 할 수 있습니다

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

4,8,16,32 등을 입력하는 것보다 비트 시프 팅이 더 쉽다는 것을 알았습니다. 컴파일 타임에 모두 수행되므로 코드에 영향을 미치지 않습니다.


답변

답변 https://stackoverflow.com/a/8462/1037948 (비트 시프 팅을 통한 선언) 및 https://stackoverflow.com/a/9117/1037948 (선언에서 조합 사용)을 사용하면 이전 값 을 비트 시프 팅 할 수 있습니다 숫자를 사용하는 것보다 반드시 권장하지는 않지만 단지 지적 할 수 있습니다.

오히려 :

[Flags]
public enum Options : byte
{
    None    = 0,
    One     = 1 << 0,   // 1
    Two     = 1 << 1,   // 2
    Three   = 1 << 2,   // 4
    Four    = 1 << 3,   // 8

    // combinations
    OneAndTwo = One | Two,
    OneTwoAndThree = One | Two | Three,
}

선언 할 수 있습니다

[Flags]
public enum Options : byte
{
    None    = 0,
    One     = 1 << 0,       // 1
    // now that value 1 is available, start shifting from there
    Two     = One << 1,     // 2
    Three   = Two << 1,     // 4
    Four    = Three << 1,   // 8

    // same combinations
    OneAndTwo = One | Two,
    OneTwoAndThree = One | Two | Three,
}

LinqPad로 확인 :

foreach(var e in Enum.GetValues(typeof(Options))) {
    string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}

결과 :

None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8


답변

선언 및 잠재적 사용법을 보여주는 예는 다음을 참조하십시오.

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");
            }
        }
    }
}


답변

C # 7에서 허용 된 답변 외에도 enum 플래그는 이진 리터럴을 사용하여 작성할 수 있습니다.

[Flags]
public enum MyColors
{
    None   = 0b0000,
    Yellow = 0b0001,
    Green  = 0b0010,
    Red    = 0b0100,
    Blue   = 0b1000
}

이 표현을 통해 표지 아래에서 플래그가 어떻게 작동하는지 명확하게 생각합니다 .


답변

나는 최근 에 비슷한 것에 대해 물었다 .

플래그를 사용하는 경우 포함 된 플래그를 쉽게 확인할 수 있도록 확장 메소드를 열거 형에 추가 할 수 있습니다 (자세한 내용은 포스트 참조).

이를 통해 다음을 수행 할 수 있습니다.

[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
}

포함 된 플래그를 확인하는 대부분의 방법보다 읽기 쉽습니다.


답변

N

기존 값 세트에 다른 플래그를 추가하려면 OR 대입 연산자를 사용하십시오.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));