열거형 (Enum, Enumeration)
열거형은 서로 연관된 상수(Constant)들의 집합을 정의할 때 사용하는 자료형이다.
공식 문서에는
열거형은 기본 정수형 숫자 형의 명명된 상수 집합으로 정의되는 값 형식 입니다.
라고 적혀있는데 무슨 말이 이렇게 어려운가...?
한 번에 무슨 말인지 잘 이해가 안 가는 표현이다.
쉽게 풀어 이야기 하자면 의미 있는 이름(label)을 숫자 값에 붙여주는 것이라고 생각하면 된다.
아래 기본적인 사용법 예시로 공식 문서대로 계절을 열거형에 넣어봤다.
enum Season
{
Spring, // 0
Summer, // 1
Autumn, // 2
Winter // 3
}
아무 값도 지정하지 않으면 0부터 시작해서 순서대로 1씩 증가한다
각 상수와 숫자가 붙여져있는 값으로 Season.Autumn을 출력하면 2가 나온다.
이렇게 열거형은 기본 값이 int지만 다른 정수형을 지정할 수도 있다.
enum Season : long
{
Spring, // 0
Summer, // 1
Autumn, // 2
Winter // 3
}
이런 식으로 말이다.
그리고 기본 0부터 시작하는 것도 바꿔줄 수 있고, 중간에도 바꿔 줄 수 있다.
다음 열거형 자료는 지정한 값부터 다시 세어진다.
enum TestEnum
{
One = 1, // 1
Two, // 2
Three, // 3
Four, // 4
Hundred, // 100
Hello, // 101
DotNet, // 102
Bald // 103
}
또한 C#에서 모든 값 형식은 0을 기본값으로 가지는데
enum 또한 값 형식의 데이터이기 때문에 0을 자동으로 기본값을 가진다.
즉 위 열거형에 없는 Test.Genius 를 출력하려 하면 0이 출력 된다.
그런데 여기서 또 웃기는 건 정의되지 않은 값도 들어올 수 있다는 점이다.
예를들어
(TestEnum)100 을 입력하면 Hundred가 나온다.
하지만 (TestEnum)1000 을 입력하면 그대로 1000이 나오는 걸 볼 수 있다.
bool isValid = Enum.IsDefined(typeof(TestEnum), 1000);
Console.WriteLine(isValid); // False
C#과 .NET 공식 문서에서도 이걸 텍스트로 설명하고 있지만 언어로 풀어서 보면 다시 봐도 무슨 말인지 잘 이해가 안 간다.
근데 친절하게도 예시 코드에 대놓고 보여주고 있었다.
public enum Season
{
Spring,
Summer,
Autumn,
Winter
}
public class EnumConversionExample
{
public static void Main()
{
Season a = Season.Autumn;
Console.WriteLine($"Integral value of {a} is {(int)a}"); // output: Integral value of Autumn is 2
var b = (Season)1;
Console.WriteLine(b); // output: Summer
var c = (Season)4;
Console.WriteLine(c); // output: 4
}
}
Season 열거형에 4가 없는데 4를 입력했더니 정수형 4가 그대로 출력되는 예시다.
또한 Switch 문에서 활용하기에도 아주 유리하다.
이 부분은 열거형 심화 문제를 해결해 보는 것으로 알아보자.
문제
누군가가 만든 프로그램에서, 플레이어의 현재 행동이 int state 로 정의되어 있습니다. state변수에 1이 담겨 있으면 idle, 2가 담겨있으면 run, 3이 들어있으면 walk , 9가 담겨있으면 죽은 상태 입니다. 열거형을 활용하여 해당 코드를 어떻게 수정할 수 있는지 작성해주세요. 유저에게 콘솔 입력으로 1,2,3,9 외의 입력이 들어오면, 옳지 못한 입력이라고 출력 후, 다시 입력을 요구하는 기능을 만드세요.
- 제대로 입력이 되었다면, 예를 들어 run에 해당하는 상태가 입력되었다면 idle에서 run으로 바뀌었다는 멘트 출력
- 이미 idle 상태였는데 idle 상태가 또 입력되면 ‘이미 idle상태입니다’ 출력
- 입력 받고 다시 무한으로 계속 진행. 9가 입력되면 ‘죽었다는 관련 멘트’ 나오고 무한루프 종료
- 심화문제이니, 문제에 명확하지 않거나 추가하고 싶은 내용이 있다면 추가 작성
이걸 코드로 구현하면
using System;
namespace structure
{
internal class Program
{
enum state
{
None, idle = 1, run, walk, dead = 9
}
static void Main(string[] args)
{
// 플레이어의 현재 행동 정의
state preState = state.None;
state currentState;
bool isDead = false;
Console.WriteLine("-----------------------");
Console.WriteLine("동작을 선택하세요");
Console.WriteLine("1 : idle");
Console.WriteLine("2 : run");
Console.WriteLine("3 : walk");
Console.WriteLine("9 : dead");
Console.WriteLine("-----------------------");
// 입력 무한 루프 - 죽으면 종료
// 콘솔 출력
while (!isDead)
{
if (Enum.TryParse(Console.ReadLine(), out currentState))
{
switch (currentState)
{
case state.idle:
case state.run:
case state.walk:
PrintChangeState(preState, currentState);
preState = currentState;
break;
case state.dead:
PrintChangeState(preState, currentState);
preState = currentState;
isDead = true;
break;
default:
Console.WriteLine("옳지 못한 입력입니다. 1,2,3,9 중 하나를 입력하세요");
break;
}
}
else
{
Console.WriteLine("옳지 못한");
}
}
}
static void PrintChangeState (state preState, state currentState)
{
Console.Clear();
Console.WriteLine("-----------------------");
Console.WriteLine("동작을 선택하세요");
Console.WriteLine("1 : idle");
Console.WriteLine("2 : run");
Console.WriteLine("3 : walk");
Console.WriteLine("9 : dead");
Console.WriteLine("-----------------------");
if (preState != state.None)
{
Console.WriteLine($"{preState}에서 {currentState}로 바뀌었다");
}
else
{
Console.WriteLine($"{currentState}로 바뀌었다");
}
}
}
}

잘 작동한다.
실제로 유니티의 인풋 시스템도 이런 비슷한 형태로 돼있다.
정확히는 열거형이라기 보다는 구조체와 클래스로 되어있는데 구조체와 클래스에 대해서는 다음에 알아보도록 하자.
대충 열거형이 어떤 것인지 알겠는데 아직까지는 손에 익지 않는 거 같다.
열거형을 잘 활용하면 보기 값을 만들어두고 꺼내 쓸 수 있어서 코드가 가독성이 좋아지고 유지보수성이 올라가니 의식해서 사용하는 연습을 해보도록 하자.
'C#' 카테고리의 다른 글
| C# - Window11 에서 Console.SetWindowSize 안 되는 문제 (0) | 2025.09.12 |
|---|---|
| C# - 구조체 (Struct, Structure) (0) | 2025.09.12 |
| C# - 재귀함수 (Recursive Function) (0) | 2025.09.11 |
| C# - Main (0) | 2025.09.11 |
| C# - 함수 심화 문제 3종 (0) | 2025.09.11 |