1. 소개
상상해봐, 네가 인기 많은 카페의 바리스타야. 손님이 와서 다섯 가지 중 하나의 좋아하는 음료를 말해. 넌 철학 토론을 하지 않고, 메뉴를 빠르게 보고 바로 반응하지: "카푸치노? 당연하지! 여기 카푸치노 나왔어!" 만약 네가 각각의 메뉴를 if로 따로따로 체크했다면, 네 코드는 점심시간 끝난 뒤 컵 쌓인 것처럼 복잡하고 불편했을 거야.
switch 연산자는 변수의 값을 깔끔하게 체크해서 결과에 따라 다른 동작을 할 수 있게 해줘. 이건 특정 데이터 타입에서만 동작하지만(아래에서 더 설명할게), 대부분의 사용자 메뉴, 간단한 명령, 상태 판별 등에선 완전 딱이야.
2. C#에서의 클래식 switch 문법
최소한의 블록 다이어그램은 이래:
switch (표현식) {
case 값1:
// 동작
break;
case 값2:
// 동작
break;
...
default:
// 기본 동작
break;
}
예제 1: 클래식 메뉴
Console.WriteLine("음료를 선택하세요: 1 - 커피, 2 - 차, 3 - 코코아");
string input = Console.ReadLine();
int choice = int.Parse(input);
switch (choice)
{
case 1:
Console.WriteLine("커피를 선택했어. 좋은 선택이야!");
break;
case 2:
Console.WriteLine("차도 괜찮지.");
break;
case 3:
Console.WriteLine("코코아는 아늑함을 아는 사람을 위한 거야!");
break;
default:
Console.WriteLine("메뉴에 없는 음료야.");
break;
}
- switch 블록은 choice가 각 case 값과 같은지 체크해.
- 각 case마다 break;를 꼭 써야 해. 안 그러면 다음 case로 넘어가서 실행돼(아래에서 더 설명할게).
- default 블록은 else랑 비슷해. 어떤 case도 안 맞으면 실행돼.
switch가 내부적으로 어떻게 동작하는지? — 단계별로
- 먼저 switch 뒤 괄호 안의 표현식(여기선 choice 변수)이 계산돼.
- 프로그램이 그 값을 각 case 값과 차례로 비교해.
- 일치하면 그 블록의 명령문이 실행돼. 그리고 break를 만나면 switch 블록을 빠져나와.
- 어떤 case도 안 맞으면 default 블록이 실행돼(있다면).
비주얼 다이어그램
| 변수 값 | case 1 | case 2 | case 3 | default |
|---|---|---|---|---|
| 1 | + | |||
| 2 | + | |||
| 3 | + | |||
| 기타 | + |
«+» — 이 블록이 실행돼
3. 클래식 switch가 지원하는 타입은?
클래식 문법(즉, "Pattern Matching"이나 최신 기능 없이!)에서 switch는 다음을 지원해:
- 기본 정수 타입 (int, byte, char, long, short, sbyte, ushort, uint, ulong)
- 문자열 (string)
- 열거형 (enum)
- 문자 (char)
예제 2: 문자열로 분기하기
Console.WriteLine("명령어를 선택하세요: start, stop, pause");
string command = Console.ReadLine();
switch (command)
{
case "start":
Console.WriteLine("프로그램이 시작됐어!");
break;
case "stop":
Console.WriteLine("프로그램이 멈췄어.");
break;
case "pause":
Console.WriteLine("프로그램이 일시정지됐어.");
break;
default:
Console.WriteLine("알 수 없는 명령어야.");
break;
}
4. break가 왜 필요하고, 까먹으면 어떻게 돼?
초보 개발자들이 제일 많이 하는 실수는 case 안에 break;를 빼먹는 거야. 그럼 어떻게 되는지 보자.
예제 3: 다음 블록으로 떨어지기(fall-through)
int day = 2;
switch (day)
{
case 1:
Console.WriteLine("월요일");
break;
case 2:
Console.WriteLine("화요일");
case 3:
Console.WriteLine("수요일");
break;
default:
Console.WriteLine("알 수 없는 요일");
break;
}
어떻게 될까?
- 입력값은 day = 2야.
- 먼저 "화요일"이 출력돼
- break가 없으니까 바로 case 3으로 넘어가서 "수요일"도 출력돼
- 그 다음 break를 만나서 빠져나와.
화면에는 이렇게 나와:
화요일
수요일
이게 전형적인 실수야!
- 한 동작만 하고 싶으면 각 case마다 break;를 꼭 써.
- 가끔(진짜 드물게) 여러 case가 같은 로직을 써야 하면 case를 "붙여서" 쓸 수 있어(아래 참고).
5. case 값 그룹화하기
가끔 여러 값이 똑같이 동작해야 할 때가 있어. 똑같은 코드를 복붙할 필요 없지!
예제 4: 여러 case에 같은 반응
char grade = 'B';
switch (grade)
{
case 'A':
case 'B':
case 'C':
Console.WriteLine("합격!");
break;
case 'D':
case 'E':
Console.WriteLine("더 성장할 수 있어.");
break;
default:
Console.WriteLine("잘못된 점수야.");
break;
}
어떻게 동작하냐면?
- grade가 'A', 'B', 'C' 중 하나면 첫 번째 블록: "합격!"이 실행돼.
- 'D'나 'E'면 두 번째 블록.
- 그 외엔 default.
6. 클래식 switch에서 가능한 것과 불가능한 것
가능한 것:
- case에 리터럴(상수) 사용 가능. 예: case 1:, case 'A':, case "스톱":.
- enum 비교 가능.
- default는 생략 가능하지만, 보통 있으면 좋아.
불가능한 것:
- case에 변수 사용 불가(상수만 가능).
- 범위로 비교 불가(case >= 5:, case x > 10: 이런 건 안 돼!).
- double, float 등 실수형은 안 돼. 정수, string, char, enum만 가능.
- 한 case에 여러 값을 콤마로 나열 불가(case 1, 2: 이런 거 안 됨. 여러 case를 연달아 써).
7. 특징과 흔한 실수
실제 프로젝트에서 switch는 메뉴, 상태 처리, 명령, 에러 코드 등 엄청 다양한 데에 써. 근데 어떤 도구든 그렇듯이 주의할 점이 있어.
흔한 실수:
- break 빼먹기(이미 얘기했지).
- switch 표현식에 잘못된 타입 쓰기(예: double 시도).
- 문자열 대소문자 불일치(case "Start":는 "start"랑 다르게 취급됨) — 문자열은 대소문자 구분해!
- 처리 안 된 값(default 빼먹거나, 사용자가 엉뚱한 값 입력).
중첩 switch의 함정
이런 코드도 가끔 보이는데, 대부분 읽기 힘들어져. 만약 switch 안에 switch를 또 쓰고 있다면, 코드를 따로 메서드로 빼거나 OOP/enum/배열 같은 걸 쓰는 게 나을 수도 있어.
GO TO FULL VERSION