Section 22.2: Enum 값을 플래그 (flag) 로 사용하기

FlagsAttribute 를 사용하면 ToString() 메소드가 매칭되는 enum 값에 대해 동작하는 방식을 변경할 수 있다:

[Flags] enum MyEnum { // None = 0, 와 같은 값을 선언할 수는 있으나 비트 단위 (bitwise) 로 조합되어 사용될 수는 없다 FlagA = 1, FlagB = 2, FlagC = 4, FlagD = 8 // 비트 단위 (bitwise) 연산을 하용하기 위해서는 // 2 의 제곱수나 2의 제곱수의 조합을 사용해야 한다 } var twoFlags = MyEnum.FlagA | MyEnum.FlagB; // 이는 해당 변수가 갖는 모든 플래그들을 열거해 줄 것이다: "FlagA, FlagB". Console.WriteLine(twoFlags);

FlagsAttribute 속성은 열거형 상수들이 2의 제곱수 (혹은 2의 제곱수들의 조합) 이어야 하는 제약 조건이 있으며 enum 값은 기본적으로 숫자 형식이기 때문에, 내부 숫자 형식 타입의 크기에 제약을 받게 된다. 사용 가능한 가장 큰 숫자 형식 타입은 UInt64 로써, 이 타입을 사용할 경우 64 개의 각기 다른 (조합되지 않은) enum 플래그 상수를 선언할 수 있다. enum 키워드는 기본적으로 int 타입을 사용하게 되어 있으며, 이는 실제적으로 Int32 를 나타낸다. 컴파일러는 32 비트보다 더 큰 값을 선언할 수 있도록 허용하지만, 이러한 경우 경고 없이 wrap around 될 것이므로, enum 이 32 개 이상의 플래그 값을 표현해야 하는 경우에는, 기본보다 더 큰 타입을 명시적으로 기술해 주어야 한다:

public enum BigEnum : ulong { BigValue = 1 << 63 }

플래그들은 대부분 하나의 비트만으로 표현되지만, 보다 편리한 사용을 위하여 이름이 주어진 세트로 조합될 수 있다.

[Flags] enum FlagsEnum { None = 0, Option1 = 1, Option2 = 2, Option3 = 4, Default = Option1 | Option3, All = Option1 | Option2 | Option3, }

2 의 제곱수들을 10진수 형태로 일일이 기술하는 불편을 피하기 위하여, 동일한 enum 을 좌측 시프트 연산자 (<<) 를 이용하여 선언할 수도 있다.

[Flags] enum FlagsEnum { None = 0, Option1 = 1 << 0, Option2 = 1 << 1, Option3 = 1 << 2, Default = Option1 | Option3, All = Option1 | Option2 | Option3, }

C# 7.0 부터는, 2진수 리터럴 (literal) 역시 사용 가능하다.

enum 변수의 값이 특정 플래그 세트를 포함하고 있는지를 확인하기 위해서는 HasFlag 메소드를 사용할 수 있다. 예를 들어 다음과 같은 enum 이 있고

[Flags] enum MyEnum { One = 1, Two = 2, Three = 4 }

변수의 값은 다음과 같이 선언되어 있을 때,

var value = MyEnum.One | MyEnum.Two;

HasFlag 를 이용하면 특정 플래그가 설정된 상태인지를 확인할 수 있다.

if(value.HasFlag(MyEnum.One)) Console.WriteLine("Enum has One"); if(value.HasFlag(MyEnum.Two)) Console.WriteLine("Enum has Two"); if(value.HasFlag(MyEnum.Three)) Console.WriteLine("Enum has Three");

또한 enum 의 모든 플래그들을 요소 반복하여 설정된 플래그들의 목록을 확인할 수도 있다.

var type = typeof(MyEnum); var names = Enum.GetNames(type); foreach (var name in names) { var item = (MyEnum)Enum.Parse(type, name); if (value.HasFlag(item)) Console.WriteLine("Enum has " + name); }

또는

foreach(MyEnum flagToCheck in Enum.GetValues(typeof (MyEnum))) { if (value.HasFlag(flagToCheck)) { Console.WriteLine("Enum has " + flagToCheck); } }

위 세가지 예제 모두는 다음과 같은 결과를 출력하게 될 것이다:

Enum has One Enum has Two
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

+ Recent posts