코드에 적히지 않은 약속은 없는 약속이다
앞 글에서 이런 코드를 썼습니다.
switch (day)
{
case 4:
Console.WriteLine("목요일");
break;
}
돌아가는 데는 문제가 없습니다. 문제는 반년 뒤입니다.
day 에 들어 있는 4 가 목요일이라는 약속은 지금 코드 어디에도 없습니다.
사람 머릿속에만 있습니다. 한 주가 일요일부터인지 월요일부터인지,
0부터 세는지 1부터 세는지도 코드를 아무리 봐도 안 나옵니다.
뜻이 있는 값에는 이름을 붙입니다. 그래야 약속이 코드 안에 남습니다.
const 는 이렇게 생겼다
바뀌지 않는 값 하나에 이름을 붙이는 문법입니다.
const double Pi = 3.14159;
Console.WriteLine(Pi * r * r);
const 를 붙이면 두 가지가 강제됩니다.
const int MaxHp; // 컴파일 에러: 선언할 때 값을 줘야 합니다
const int MaxHp = 100;
MaxHp = 200; // 컴파일 에러: 나중에 바꿀 수 없습니다
앞에서 선언은 컴파일 시점, 할당은 실행 시점이라고 했습니다.
const 는 그 둘이 컴파일 시점 한 번으로 합쳐진 것입니다.
그래서 컴파일할 때 이미 알 수 있는 값만 들어갈 수 있습니다.
실행해 봐야 아는 값, 예를 들어 사용자가 입력한 숫자는 const 가 될 수 없습니다.
숫자를 그대로 쓰면 무슨 일이 생기나
if (hp <= 30)
{
ShowWarning();
}
if (damage > 30)
{
PlayHitEffect();
}
두 개의 30 은 뜻이 다릅니다. 하나는 경고를 띄우는 체력 기준이고,
하나는 큰 피해를 판정하는 기준입니다. 코드에는 똑같이 30 이라고만 적혀 있습니다.
경고 기준을 40으로 올리라는 요청이 오면, 파일에서 30 을 찾아
어느 쪽이 체력인지 하나씩 읽어 보고 고쳐야 합니다. 하나를 잘못 고치면
경고는 그대로고 타격 효과만 조용히 바뀝니다.
const int WarningHp = 30;
const int BigDamage = 30;
이름을 붙이면 찾을 것이 없습니다. 고칠 자리가 한 곳이고, 그 한 줄만 바꾸면 됩니다.
enum 은 이렇게 생겼다
const 는 값 하나에 이름을 붙입니다.
그런데 요일처럼 정해진 선택지가 묶음으로 있는 경우가 있습니다.
이때 쓰는 것이 enum 입니다.
enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }
Days today = Days.Monday;
Console.WriteLine(today); // Monday
이름만 나열했는데 값은 어디서 나오느냐면, 컴파일러가 0부터 붙여 줍니다.
번호가 마음에 안 들면 직접 적어도 됩니다.
enum Days { Sunday = 1, Monday, Tuesday } // 1, 2, 3
하나만 적으면 그다음부터는 이어서 붙습니다.
enum 과 switch 는 짝이다
이제 앞 글의 코드를 다시 씁니다.
switch (today)
{
case Days.Monday:
Console.WriteLine("월요일");
break;
case Days.Thursday:
Console.WriteLine("목요일");
break;
}
case 4: 였을 때와 하는 일이 똑같습니다. 달라진 것은 읽는 사람입니다.
주석도 문서도 없이 코드만 보고 뜻을 압니다.
enum 은 후보가 정해져 있고 switch 는 후보를 늘어놓는 문법이라 서로 잘 맞습니다.
Days 를 하나 늘리면 switch 에 case 를 하나 더 적으면 되고,
그 자리를 빠뜨렸는지도 눈으로 셀 수 있습니다.
enum 도 결국 정수다
여기서 한 가지 짚고 넘어가야 합니다.
enum 은 새로운 종류의 값이 아니라 정수에 이름을 씌운 것입니다.
바탕에 깔린 값은 그대로 int 입니다.
Console.WriteLine((int)Days.Thursday); // 4
그래서 이런 것도 컴파일이 됩니다.
Days today = (Days)99;
Days 에 99번은 없습니다. 그래도 에러가 나지 않습니다.
앞에서 본 대로 캐스팅은 “내가 책임진다”는 표시이고,
컴파일러는 여기서 값의 범위를 확인해 주지 않습니다.
앞 글에서 default 를 적어 두라고 한 이유가 여기입니다.
enum 을 쓰면 후보가 다 막힌 것처럼 보이지만, 실제로 막힌 것은
실수로 다른 값을 적는 일이지 다른 값이 들어오는 일이 아닙니다.
정리
- 뜻이 있는 값을 숫자 그대로 쓰면, 그 뜻은 코드 밖에만 남습니다.
const는 값 하나에 이름을 붙입니다. 선언할 때 값을 줘야 하고 나중에 못 바꿉니다.const에는 컴파일할 때 이미 아는 값만 들어갑니다.enum은 정해진 선택지 묶음에 이름을 붙입니다. 적은 순서대로 0부터 번호가 붙습니다.enum과switch는 짝입니다. 후보가 정해져 있다는 성질이 같습니다.enum의 바탕은 정수입니다. 캐스팅으로 후보 밖의 값도 만들어지므로default는 남겨 둡니다.