1. 소개
프로그래밍하다 보면 미리 정해진, 한정된 선택지 리스트를 다루는 일이 진짜 많아. 예를 들면: 요일, 신호등 색깔, 게임 난이도, 주문 상태 같은 거. 이런 각각의 선택지는 보통 고정된 값으로 표현되지. 오늘의 주제인 열거형(enum)이 바로 여기서 등장해.
열거형은 여러 개의 이름이 붙은 상수 집합을 선언할 수 있게 해주는 특별한 데이터 타입이야.
enum은 마치 칸마다 라벨이 붙은 상자 같은 거고, 각 라벨은 고유한 이름과 숫자가 연결되어 있어.
- 코드가 읽기 쉽고 자기 설명적이 돼;
- 0, 1, 2 같은 정체불명의 "매직 넘버" 대신 DayOfWeek.Monday나 TrafficLight.Red처럼 의미 있는 이름을 쓸 수 있어;
- 잘못된 값을 넣으려고 하면 컴파일러가 에러를 내줄 거야;
- 사실 각 요소는... 그냥 평범한 정수야! (이건 좀 있다가 다시 얘기할게.)
2. 열거형 선언 문법
우리 첫 번째 열거형을 만들어보자 — 날씨 타입을 위한 거야. 이렇게 쓸 수 있어:
// 날씨 상태 열거형
public enum WeatherCondition
{
Sunny, // 0
Cloudy, // 1
Rainy, // 2
Stormy, // 3
Snowy // 4
}
- enum 키워드로 새로운 타입을 정의해.
- 중괄호 안에 선택지 이름을 써. 기본적으로 각 선택지는 0부터 시작하는 정수값이 자동으로 할당돼 (Sunny == 0, Cloudy == 1 등).
- 값을 직접 지정할 수도 있어:
public enum WeatherCondition
{
Sunny = 1,
Cloudy = 2,
Rainy = 4,
Stormy = 8,
Snowy = 16
}
이렇게 하면 외부 표준이나 프로토콜에 맞춰야 할 때 편해.
3. 열거형 사용하기
우리 작은 콘솔 앱을 만들었다고 해보자. 날씨에 따라 반응하는 프로그램이야.
// 앱 클래스
class Program
{
static void Main()
{
// 날씨 상태 저장에 열거형 사용
WeatherCondition todayWeather = WeatherCondition.Sunny;
// 화면에 출력
Console.WriteLine($"오늘 날씨: {todayWeather} ({(int)todayWeather})");
// 날씨가 바뀌는 걸 흉내내보자
todayWeather = WeatherCondition.Rainy;
Console.WriteLine($"앗! 날씨가 바뀌었어: {todayWeather} ({(int)todayWeather})");
}
}
무슨 일이 일어날까?
오늘 날씨: Sunny (0)
앗! 날씨가 바뀌었어: Rainy (2)
- todayWeather는 문자열도 아니고 숫자도 아니고, 열거형의 요소야.
- (int)로 캐스팅하면 해당 값의 "숫자 코드"를 볼 수 있어.
참고로, 열거형은 조건문이랑도 잘 어울려:
if (todayWeather == WeatherCondition.Rainy)
Console.WriteLine("우산 챙겨!");
4. enum의 실전 활용 예시
열거형은 어디서 쓰일까?
- 비즈니스 앱: 주문 상태 (New, Processing, Shipped, Cancelled).
- 유저 관리 시스템: 권한 레벨 (User, Moderator, Admin).
- 게임: 캐릭터 상태 (Idle, Moving, Jumping, Falling).
- GUI: 버튼, 메시지, 아이콘 색상 등.
.NET에서라면 거의 표준 라이브러리의 절반에서 열거형을 볼 수 있어! 예를 들어 파일 작업할 때 파일 열기 모드(읽기, 쓰기, 생성 등)도 열거형으로 되어 있지.
5. 명시적 값과 값의 범위
가끔 코드에서 쓰는 int 값 집합을 enum으로 바꾸고 싶을 때가 있어. 이건 진짜 간단해:
public enum CompassDirection
{
North = 10,
East = 20,
South = 30,
West = 40
}
이제 CompassDirection.North = 10, East = 20 등등. 만약 어떤 요소에 값을 안 주면, 이전 값에서 +1이 자동으로 할당돼.
저장 타입
기본적으로 enum은 int(4바이트 정수)로 저장돼. 근데 메모리 아끼고 싶으면 기본 타입을 직접 지정할 수도 있어:
public enum TinyEnum : byte
{
First, // 0
Second, // 1
Third // 2
}
이제 열거형 값 하나가 딱 1바이트!
가능한 타입 리스트: byte, sbyte, short, ushort, int, uint, long, ulong.
6. enum과 숫자/문자열 간 변환
enum ↔ int 변환:
enum을 int로, int를 enum으로 바꾸는 건 그냥 타입 캐스팅만 하면 돼:
WeatherCondition current = WeatherCondition.Cloudy;
int number = (int)current; // 1이 나옴
WeatherCondition fromNumber = (WeatherCondition)2; // Rainy가 나옴
enum ↔ string 변환:
enum을 문자열로 바꾸려면 ToString()만 호출하면 돼.
// enum을 문자열로 변환
string name = WeatherCondition.Stormy.ToString(); // "Stormy"
// 문자열을 enum으로 변환 (Enum.Parse 사용)
WeatherCondition parsed = (WeatherCondition)Enum.Parse(typeof(WeatherCondition), "Stormy");
// Enum.TryParse도 쓸 수 있어
WeatherCondition parsedOk;
if (Enum.TryParse("Snowy", out parsedOk))
{
Console.WriteLine(parsedOk); // Snowy
}
흔한 실수:
숫자를 enum으로 캐스팅할 때, 해당 값이 정의되어 있지 않아도 컴파일러는 에러를 안 내. 그냥 "가짜" 상태가 만들어질 뿐이야.
예시:
WeatherCondition weird = (WeatherCondition)999;
Console.WriteLine(weird); // 999 (이게 "Unknown"으로 바뀌지 않아!)
즉, 이런 변환을 할 땐 개발자가 신경 써야 해.
7. switch와 enum은 찰떡궁합
열거형(enum)은 switch문이랑 진짜 잘 어울려. 여러 if-else 없이도 각 값에 따라 "반응"하는 코드를 깔끔하게 쓸 수 있지.
예시: 날씨에 따른 반응
public enum WeatherCondition
{
Sunny,
Cloudy,
Rainy,
Stormy,
Snowy
}
WeatherCondition today = WeatherCondition.Rainy;
switch (today)
{
case WeatherCondition.Sunny:
Console.WriteLine("맑음! 산책 가자.");
break;
case WeatherCondition.Cloudy:
Console.WriteLine("흐림. 가디건 챙겨.");
break;
case WeatherCondition.Rainy:
Console.WriteLine("비 온다. 우산 잊지 마!");
break;
case WeatherCondition.Stormy:
Console.WriteLine("폭풍! 집에 있는 게 좋아.");
break;
case WeatherCondition.Snowy:
Console.WriteLine("눈 온다 — 모자 써!");
break;
default:
Console.WriteLine("알 수 없는 날씨...");
break;
}
- 각 case는 열거형의 한 값을 의미해.
- 아무 값에도 해당 안 되면 default가 실행돼 (예상치 못한 값이 들어올 때 유용해).
enum + switch 조합의 장점?
- 코드가 읽기 쉬움: 가능한 모든 경우가 case로 한눈에 보여.
- 확장도 쉬움: 새로운 날씨 타입 추가하면 case만 하나 더 쓰면 돼.
- 안전함: (C# 8.0부터) 모든 경우를 다 처리했는지 컴파일러가 체크해줄 수도 있어.
예시: 게임용 enum과 로직
public enum GameState
{
Start,
Playing,
Paused,
GameOver
}
void PrintState(GameState state)
{
switch (state)
{
case GameState.Start:
Console.WriteLine("게임에 오신 걸 환영해!");
break;
case GameState.Playing:
Console.WriteLine("게임 중. 행운을 빌어!");
break;
case GameState.Paused:
Console.WriteLine("일시정지. 잠깐 쉬어가.");
break;
case GameState.GameOver:
Console.WriteLine("게임 끝. 다시 도전해봐!");
break;
default:
Console.WriteLine("알 수 없는 게임 상태.");
break;
}
}
팁:
- 비슷한 동작이 여러 값에 필요하면 묶어서 처리해도 돼:
switch (today)
{
case WeatherCondition.Rainy:
case WeatherCondition.Stormy:
Console.WriteLine("우산이랑 따뜻한 옷 챙겨!");
break;
}
- default도 꼭 써서 예상치 못한 값도 처리해 (예를 들어 누가 숫자를 enum으로 바로 캐스팅했을 때).
- switch로 상태머신, 메뉴, 고정된 선택지 시스템 등도 쉽게 만들 수 있어.
8. 열거형과 .NET의 주요 메서드/서비스
.NET에는 열거형을 위한 유용한 메서드가 많아:
- Enum.GetNames(typeof(WeatherCondition)) — 모든 이름 가져오기.
- Enum.GetValues(typeof(WeatherCondition)) — 모든 값 가져오기.
- Enum.IsDefined(typeof(WeatherCondition), "Rainy") — 해당 멤버가 있는지 확인.
- 문서: System.Enum
모든 날씨 타입 출력 예시:
foreach (var name in Enum.GetNames(typeof(WeatherCondition)))
{
Console.WriteLine(name);
}
9. 흔한 실수와 "지뢰"
- 열거형 대신 "매직 넘버"를 써서 코드가 읽기 힘들어짐.
- 열거형에 정의되지 않은 값 처리를 안 함 (숫자 캐스팅 예시 참고).
- 의미 없는 이름(Value1, Value2...)을 써서 나중에 아무도 뭔지 모르게 됨.
- 한 열거형에 여러 종류의 의미를 섞어서 단일 책임 원칙을 깨뜨림.
최고의 방법: 선택지가 정해져 있으면 항상 열거형을 쓰고, 각 요소에 의미 있고 자기 설명적인 이름을 붙여!
GO TO FULL VERSION