etc./StackOverFlow

C#에서 [Flags] Enum Attribute는 무엇을 의미합니까?

청렴결백한 만능 재주꾼 2022. 2. 8. 08:37
반응형

질문자 :Brian Leahy


때때로 다음과 같은 열거형이 표시됩니다.

 [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] 자동으로 열거형 값을 2의 거듭제곱으로 만들지 않는다는 점에 유의하는 것도 중요합니다. 숫자 값을 생략하면 기본적으로 값이 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... }

커버 아래

이것은 열거에서 2의 거듭제곱을 사용했기 때문에 작동합니다. 덮개 아래에서 열거 값은 이진 1과 0에서 다음과 같이 보입니다.

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

마찬가지로, 당신은 바이너리 비트를 사용하여 빨강, 녹색, 파랑에 속성 AllowedColors을 설정 한 후 OR | 연산자, AllowedColors 는 다음과 같습니다.

 myProperties.AllowedColors: 00001110

따라서 값을 검색할 때 실제로 값에 대해 비트 AND & 를 수행하고 있습니다.

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

없음 = 0 값

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

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

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

msdn 에서 flags 속성과 사용법에 대한 자세한 정보를 찾을 수 있으며 msdn에서 플래그를 디자인할 수 있습니다.


andynil

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

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

4,8,16,32 등을 입력하는 것보다 비트 이동이 더 쉽습니다. 컴파일 타임에 모두 완료되기 때문에 코드에 영향을 미치지 않습니다.


Orion Edwards

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

drzaus

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

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

OJ.

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

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

나는 이 표현을 통해 깃발이 덮개 아래에서 어떻게 작동하는지 명확히 알 수 있다고 생각합니다.


Thorkil Holm-Jacobsen

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

플래그를 사용하는 경우 열거형에 확장 메서드를 추가하여 포함된 플래그를 더 쉽게 확인할 수 있습니다(자세한 내용은 게시물 참조)

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

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

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


Keith

플래그로 작업할 때 나는 종종 추가 None 및 All 항목을 선언합니다. 이는 모든 플래그가 설정되었는지 또는 플래그가 설정되지 않았는지 확인하는 데 유용합니다.

 [Flags] enum SuitsFlags { None = 0, Spades = 1 << 0, Clubs = 1 << 1, Diamonds = 1 << 2, Hearts = 1 << 3, All = ~(~0 << 4) }

용법:

 Spades | Clubs | Diamonds | Hearts == All // true Spades & Clubs == None // true


2019-10 업데이트:

C# 7.0부터 이진 리터럴을 사용할 수 있습니다. 이 리터럴은 읽기가 더 직관적일 수 있습니다.

 [Flags] enum SuitsFlags { None = 0b0000, Spades = 0b0001, Clubs = 0b0010, Diamonds = 0b0100, Hearts = 0b1000, All = 0b1111 }

Jpsy

@니도노쿠

기존 값 집합에 다른 플래그를 추가하려면 OR 할당 연산자를 사용합니다.

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

steve_c

Mode.Write 를 추가하려면:

 Mode = Mode | Mode.Write;

David Wengier

[정보] 나에게 지나치게 자세한 뭔가가있다 if ((x & y) == y)... 구조, 특히 xy 플래그의 두 화합물 세트이고, 당신은 어떤 중복이 있는지 알고 싶습니다.

이 경우 비트마스크를 한 후 0이 아닌 값[1]이 있는지만 알아야 합니다.

[1] Jaime의 의견을 참조하십시오. 우리가 진정으로 비트마스킹 을 한다면 결과가 긍정적인지 확인하기만 하면 됩니다. enum s 는 음수가 될 수 있기 때문에[Flags] 속성 > 0 보다는 != 0 으로 코딩하는 것이 방어적입니다.

@andnil의 설정을 기반으로 구축...

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BitFlagPlay { class Program { [Flags] public enum MyColor { Yellow = 0x01, Green = 0x02, Red = 0x04, Blue = 0x08 } static void Main(string[] args) { var myColor = MyColor.Yellow | MyColor.Blue; var acceptableColors = MyColor.Yellow | MyColor.Red; Console.WriteLine((myColor & MyColor.Blue) != 0); // True Console.WriteLine((myColor & MyColor.Red) != 0); // False Console.WriteLine((myColor & acceptableColors) != 0); // True // ... though only Yellow is shared. Console.WriteLine((myColor & MyColor.Green) != 0); // Wait a minute... ;^D Console.Read(); } } }

ruffin

플래그를 사용하면 열거 내에서 비트마스킹을 사용할 수 있습니다. 이렇게 하면 지정된 값을 유지하면서 열거형 값을 결합할 수 있습니다.

 [Flags] public enum DashboardItemPresentationProperties : long { None = 0, HideCollapse = 1, HideDelete = 2, HideEdit = 4, HideOpenInNewWindow = 8, HideResetSource = 16, HideMenu = 32 }

Jay Mooney

누군가 이미 이 시나리오를 발견했다면 사과드립니다. 반사에서 볼 수 있는 플래그의 완벽한 예입니다. 예 바인딩 플래그 ENUM .

 [System.Flags] [System.Runtime.InteropServices.ComVisible(true)] [System.Serializable] public enum BindingFlags

용법

 // BindingFlags.InvokeMethod // Call a static method. Type t = typeof (TestClass); Console.WriteLine(); Console.WriteLine("Invoking a static method."); Console.WriteLine("-------------------------"); t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object [] {});

kbvishnu

  • 열거 가능한 값이 열거형 멤버의 컬렉션을 나타낼 때 플래그가 사용됩니다.

  • 여기서는 비트 연산자를 사용합니다. | 그리고 &

  • 예시

     [Flags] public enum Sides { Left=0, Right=1, Top=2, Bottom=3 } Sides leftRight = Sides.Left | Sides.Right; Console.WriteLine (leftRight);//Left, Right string stringValue = leftRight.ToString(); Console.WriteLine (stringValue);//Left, Right Sides s = Sides.Left; s |= Sides.Right; Console.WriteLine (s);//Left, Right s ^= Sides.Right; // Toggles Sides.Right Console.WriteLine (s); //Left

Mukesh Pareek

출처 : http:www.stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c

반응형