
프로그래밍을 하다 보면 한정된 값 집합을 다루어야 할 때가 있습니다.
예를 들어, 요일(월~일), 상태(시작/진행/완료) 같은 경우가 그렇죠.
이런 상황에서는 열거형(Enum)을 사용해서
코드의 가독성과 안정성을 크게 높일 수 있습니다.
"월요일은 1, 화요일은 2..." 처럼, 숫자에 특별한 의미를 부여한 경우
한참 뒤에 코드를 다시 보거나, 동료가 이 코드를 볼 때는 어떨까요?
"이 6은 대체 무슨 값이지? 마법의 숫자(Magic Number)인가?"
이렇게 의미를 정확히 알 수 없는 숫자들이 코드 안에
하드 코딩 되어 있으면 매직 넘버(Magic Number)라고 합니다.
매직 넘버는 코드의 가독성을 떨어뜨릴 뿐만 아니라,
유지보수 시 심각한 버그를 유발하는 주범이 되기도 합니다.
실수로 잘못된 값을 넣어도 컴파일러는 아무런 경고도 해주지 않습니다.
[코드]
using System;
class Program
{
static void Main()
{
PrintDayMessage(1); // 1이 월요일이라는 것을 기억해야만 함
PrintDayMessage(8); // 8은 요일에 없는데도 문제없이 실행됨 (논리적 오류!)
}
static void PrintDayMessage(int dayOfWeek)
{
string message = dayOfWeek switch
{
1 => "월요일... 힘내세요!",
6 or 7 => "신나는 주말입니다!",
_ => "평일이네요!"
};
Console.WriteLine(message);
}
}
[실행 결과]
월요일... 힘내세요!
평일이네요!
열거형은 상수들의 집합에 의미 있는 이름을 붙여준 것입니다.
관련된 상수가 한 곳에 모여 있어 관리가 편합니다.
enum키워드를 사용해 열거형을 정의합니다.
열거형의 멤버들은 특별히 값을 지정하지 않으면,
0부터 시작하는 정수 값을 자동으로 부여받습니다.
enum RGB
{
Red, // 0
Green, // 1
Blue // 2
}
원하는 값으로 시작하거나 특정 값을 직접 할당할 수도 있습니다.
enum Season
{
Spring = 3, // 3
Summer = 5, // 5
Autumn, // 6
Winter // 7
}
열거형은 내부적으로 정수형(기본값: int)으로 처리됩니다.
즉, ‘여러 이름이 있는 상수 값을 하나의 형식(Type)으로 묶은 것’입니다.
RGB는 형식이고, RGB.Red, RGB.Green같은 것들이 그 형식의 상수입니다.
이러한 특성을 가지고 있어 열거형은 형변환이 가능합니다.
[코드]
using System;
enum RGB
{
Red, // 0
Green, // 1
Blue // 2
}
class Program
{
static void Main()
{
// 기본 사용
RGB myColor = RGB.Red;
Console.WriteLine($"내 색상: {myColor}");
// 1. 열거형 -> 정수
// 열거형 멤버를 해당하는 정수 값으로 변환하려면 간단히 (int)로 캐스팅합니다.
int greenValue = (int)RGB.Green;
Console.WriteLine($"RGB.Green의 정수 값: {greenValue}");
// 2. 열거형 -> 문자열
// ToString() 메서드를 호출하면 열거형 멤버의 이름을 문자열로 얻을 수 있습니다.
string blueString = RGB.Blue.ToString();
Console.WriteLine($"RGB.Blue의 문자열 값: '{blueString}'");
// 3. 정수 -> 열거형
// 정수 값을 해당하는 열거형 멤버로 변환할 수 있습니다. 이 역시 명시적 캐스팅이 필요합니다.
int value = 0;
RGB fromIntValue = (RGB)value;
Console.WriteLine($"정수 {value}로부터 변환: {fromIntValue}");
// 4. 문자열 -> 열거형
// 문자열을 해당하는 열거형 멤버로 변환하려면 Enum.Parse() 메서드를 사용합니다.
string colorString = "Blue";
RGB fromStringValue = (RGB)Enum.Parse(typeof(RGB), colorString);
Console.WriteLine($"'{colorString}' 문자열로부터 변환: {fromStringValue}");
// 5. 주의: 정의되지 않은 정수 값 변환
// 열거형에 정의되지 않은 정수 값도 에러 없이 형변환됩니다.
int invalidValue = 10;
RGB invalidColor = (RGB)invalidValue;
Console.WriteLine($"정의되지 않은 값 {invalidValue} 변환: {invalidColor}");
Console.WriteLine($"값이 유효한가? {Enum.IsDefined(typeof(RGB), invalidValue)}");
}
}
[실행 결과]
내 색상: Red
RGB.Green의 정수 값: 1
RGB.Blue의 문자열 값: 'Blue'
정수 0로부터 변환: Red
'Blue' 문자열로부터 변환: Blue
정의되지 않은 값 10 변환: 10
값이 유효한가? False
열거형의 기본 형식은 int이지만, 필요하면
byte, long 등 다른 정수형으로 지정할 수 있습니다.
enum Status : byte
{
Ready = 1,
Running = 2,
Completed = 3
}
여러 상태를 조합해야 할 때는 [Flags]특성을 붙여 사용합니다.
열거형에서 비트 연산(|, &)은 [Flags]속성이 없어도 동작하지만,
[Flags]를 붙이면 비트 연산의 의도를 명확히 하며, ToString()출력을 개선합니다.
[코드]
using System;
[Flags]
enum FileAccess
{
None = 0, // 열거형에서 [Flags] 속성을 사용할 때는 0 값을 포함하는 것이 일반적입니다.
Read = 1,
Write = 2,
Execute = 4
}
class Program
{
static void Main()
{
FileAccess access = FileAccess.Read | FileAccess.Write;
Console.WriteLine(access); // Read, Write
}
}
[실행 결과]
Read, Write
실무에서는 다음과 같은 규칙을 준수해야 합니다.
Day, FileAccess, Status…Monday, Tuesday, Ready, Running…Days ⮕ Day[Flags]속성이 적용된 열거형은 복수형 이름 사용 권장: Day ⮕ Days[Flags]속성 사용 시 열거형의 멤버에서 None = 0을 포함할 것열거형은 switch와 함께 사용될 때 그 진가가 더욱 발휘됩니다.
코드가 훨씬 더 깔끔하고 구조적으로 변합니다.
[코드]
using System;
class Program
{
enum Day
{
Monday, // 월요일
Tuesday, // 화요일
Wednesday, // 수요일
Thursday, // 목요일
Friday, // 금요일
Saturday, // 토요일
Sunday // 일요일
}
static void Main()
{
Day today = Day.Sunday;
PrintDayMessage(today);
}
static void PrintDayMessage(Day dayOfWeek)
{
string message = dayOfWeek switch
{
Day.Monday => "월요일... 힘내세요!",
Day.Saturday or Day.Sunday => "신나는 주말입니다!",
_ => "평일이네요!"
};
Console.WriteLine(message);
}
}
[실행 결과]
신나는 주말입니다!