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/
'번역 > C# Notes for Professionals' 카테고리의 다른 글
22.4: 비트 논리 연산 (bitwise logic) 을 통해 플래그 스타일의 enum 값 검사하기 (0) | 2021.06.18 |
---|---|
22.3: 플래그 선언을 위한 << 표기법 (0) | 2021.05.18 |
22.1: Enum 에 대한 기본 사항들 (0) | 2021.05.12 |
22: Enum (0) | 2021.05.12 |
21.1: 배열의 내용을 주어진 값만큼 shift rotate 시키는 generic 메소드 예제 (0) | 2021.05.10 |