Menu

C# switch 문: case, break, default와 여러 case 묶기

C# switch 문이 동작하는 방식: int, string, char, enum 값으로 분기하기, 모든 case에 break가 필요한 이유(CS0163 오류), 여러 값을 위한 case 레이블 겹치기, goto case, default, 문자열의 대소문자 구분, when을 쓰는 패턴 case 레이블을 알아봅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

switch 문은 하나의 값을 상수 case 레이블 목록과 비교하고 일치하는 섹션을 실행합니다. C#에서는 모든 섹션이 break(또는 섹션을 빠져나가는 다른 문장)로 끝나야 하므로, 한 case가 조용히 다음 case로 이어지는 일이 절대 없습니다.

출력:

200: OK
302: redirect
404: not found
500: unhandled status

괄호 안의 값은 한 번 평가되어 각 레이블과 비교됩니다. default는 아무것도 일치하지 않을 때 실행되며, 선택 사항이고 목록 어디에나 둘 수 있지만 보통 마지막에 둡니다. 일치하는 것도 default도 없으면 switch 전체가 아무 일도 하지 않습니다.

모든 섹션에는 break가 필요합니다

C, C++, Java, JavaScript에서는 break를 잊으면 실행이 다음 case로 미끄러져 들어갑니다. C#은 이 실수를 컴파일 오류로 만듭니다:

switch (level)
{
    case 1:
        Console.WriteLine("read");
        // error CS0163: Control cannot fall through from one case label ('case 1:') to another
    case 2:
        Console.WriteLine("write");
        break;
}

규칙은 섹션의 문장 목록 끝에 도달할 수 없어야 한다는 것입니다. 보통은 break로 이를 만족시키지만, 섹션을 빠져나가는 것이면 무엇이든 됩니다:

  • return은 메서드 전체를 빠져나가며, 작은 헬퍼 안에서는 가장 깔끔한 형태인 경우가 많습니다.
  • throw는 절대 나오면 안 되는 값에 대해 예외를 발생시킵니다.
  • continue는 switch가 루프 안에 있을 때 다음 반복으로 건너뜁니다.
  • goto case와 goto default는 의도적으로 다른 섹션으로 점프합니다.

마지막 섹션도 예외가 아닙니다. 맨 아래의 default:에 break가 없으면 CS8070 Control cannot fall out of switch from final case label ('default:')로 실패합니다.

한 case에 여러 값

사이에 문장이 없는 레이블들은 그 아래 섹션을 공유합니다. 빈 레이블은 어떤 코드도 숨길 수 없으므로, C#이 허용하는 유일한 종류의 fall through입니다:

출력:

'O' is a vowel
'k' is a consonant or symbol
' ' is a space
'7' is a digit

여기서는 각 섹션이 return으로 끝나므로 break가 필요 없습니다(return 뒤의 break는 도달할 수 없는 코드가 됩니다). 같은 값을 가진 두 레이블은 오류 CS0152 The switch statement contains multiple cases with the label value '1'이며, 모든 레이블은 컴파일 시점 상수여야 합니다. case에 변수를 쓰면 "a constant value is expected"로 실패합니다.

문자열로 switch하기

정수 다음으로 가장 흔한 switch 값은 문자열입니다. 비교는 대소문자를 구분하는 서수 비교이므로, switch하기 전에 입력을 정규화하세요:

출력:

Starting the server
Stopping the server
Server is running
Unknown command: restart
Unknown command: (none)

ToLowerInvariant가 없다면 "STOP"은 default로 갑니다. null 값으로 switch하는 것은 허용됩니다. 어떤 문자열 상수에도 걸리지 않고 default로 떨어지므로 switch 자체는 예외를 던지지 않습니다.

열거형으로 switch하기

열거형은 switch가 만들어진 이유입니다. 이름 붙은 값의 닫힌 집합이기 때문입니다.

출력:

Pending: wait for payment
Paid: pack and ship
Shipped: track the parcel
Delivered: nothing, order is closed
Cancelled: nothing, order is closed
ArgumentOutOfRangeException for value 42

컴파일러는 switch 문이 열거형의 모든 멤버를 다루는지 검사하지 않으며, 열거형 변수는 기반 타입의 어떤 정수든 담을 수 있습니다((OrderStatus)42도 허용됩니다). 예외를 던지는 default는 빠뜨린 case를 조용히 아무것도 안 하는 대신 즉각적이고 분명한 실패로 바꿔 줍니다.

goto case와 goto default

한 case가 정말로 다른 case로 이어져야 할 때, C#은 점프를 직접 쓰게 합니다:

출력:

admin:
  manage users
  edit posts
  read posts
editor:
  edit posts
  read posts
guest:
  read posts

goto case는 같은 switch의 레이블 중 하나와 일치하는 상수를 받습니다. 실제 코드에서는 드뭅니다. 공유 동작은 보통 여러 case가 호출하는 메서드로 만드는 편이 더 명확합니다. 그래도 "C#에서 fall through는 어떻게 하나요?"에 대한 답은 이것입니다.

case 안의 변수

switch 블록 전체가 하나의 범위이므로 두 case에서 같은 이름의 변수를 선언할 수 없습니다:

switch (shape)
{
    case "square":
        int area = side * side;
        break;
    case "rectangle":
        int area = width * height;   // error CS0128: A local variable or function named 'area' is already defined in this scope
        break;
}

각 섹션 본문을 중괄호로 감싸면 섹션마다 자기 범위가 생깁니다: case "square": { int area = side * side; ... break; }.

루프 안의 break

case 안의 break는 둘러싼 루프가 아니라 switch를 빠져나갑니다. continue는 반대입니다. switch는 루프가 아니므로 continue는 루프의 다음 반복으로 갑니다.

출력:

end marker found
Total: 134

루프는 "end" 뒤에도 계속 돌아서 99를 더했습니다. switch 안에서 루프를 멈추려면 플래그를 설정하고 switch 뒤에서 검사하거나, 루프를 메서드로 옮기고 return하세요. break와 continue 페이지에서 선택지를 비교합니다.

패턴 case 레이블과 when

C# 7.0부터는 case 레이블이 상수 대신 패턴이 될 수 있습니다. 값의 타입을 검사하고 when 조건을 덧붙일 수 있습니다. 최신 C# 코드에서 흔한 형태입니다:

static string Describe(object value)
{
    switch (value)
    {
        case null:
            return "nothing";
        case int n when n < 0:
            return $"negative int {n}";
        case int n:
            return $"int {n}";
        case string s when s.Length == 0:
            return "empty string";
        case string s:
            return $"string \"{s}\"";
        default:
            return $"other: {value.GetType().Name}";
    }
}

패턴에서는 순서가 중요합니다. 처음 일치하는 case가 이기며, 앞의 case가 이미 모두 덮어서 도달할 수 없는 case가 있으면 컴파일러가 오류를 보고합니다(case int n when n < 0: 위에 case int n:을 두면 실패합니다). when 절은 상수 case에도 쓸 수 있습니다: case 0 when isAdmin:. C# 9는 관계 패턴과 논리 패턴을 추가해서 case를 case >= 90:이나 case 'a' or 'e' or 'i':로 쓸 수 있습니다.

패턴이 없는 C# 7에서는 같은 타입 분기를 is 타입 패턴을 쓴 if 체인으로 씁니다:

출력:

negative int -3
int 12
empty string
string "hi"
other: Decimal
nothing

switch의 모든 분기가 값만 계산한다면 switch 식이 더 짧습니다: var grade = score switch { >= 90 => "A", >= 80 => "B", _ => "C" };. switch 식 페이지에서 문법, 패턴, 완전성 규칙을 다룹니다.

switch할 수 있는 값

값 타입상수 case참고
int, long, byte와 그 밖의 정수가능전형적인 경우
char가능case 'a':
string가능서수, 대소문자 구분, null은 default로
bool가능허용되지만 if가 더 명확
모든 enum가능완전성 검사 없음
double, decimalC# 7부터상수만, 범위에는 C# 9 관계 패턴 필요
그 밖의 모든 타입C# 7부터타입 패턴으로, case Circle c:

자주 묻는 질문

C# switch에서 break는 꼭 필요한가요?

모든 case 섹션은 섹션을 빠져나가는 문장으로 끝나야 합니다. 보통 break이지만 return, throw, (루프 안의) continue, goto case도 됩니다. 섹션 끝에서 다음 섹션으로 흘러 들어가는 것은 컴파일 오류 CS0163 Control cannot fall through from one case label ('case 1:') to another이며, 마지막 섹션도 마찬가지입니다.

C# switch의 한 case에서 여러 값을 처리하려면 어떻게 하나요?

레이블 사이에 아무것도 두지 않고 겹쳐 씁니다: case "sat": case "sun": Console.WriteLine("weekend"); break;. 빈 case 레이블은 다음 레이블로 흘러갈 수 있고, 문장이 들어 있는 섹션만 break로 끝나야 합니다. C# 9 이상에서는 패턴 case로 case 1 or 2 or 3:이라고 쓸 수도 있습니다.

C#에서 문자열 switch는 대소문자를 구분하나요?

네. 문자열 case는 대소문자를 구분하는 서수 비교로 비교하므로 "Yes"는 case "yes":에 걸리지 않습니다. 먼저 switch (input.Trim().ToLowerInvariant())로 값을 정규화하세요. null 문자열은 어떤 상수 case에도 걸리지 않고 default로 갑니다.

C# switch도 C나 Java처럼 fall through할 수 있나요?

암묵적으로는 안 됩니다. 한 case가 다른 case로 이어지게 하려면 goto case <value>;나 goto default;로 명시하세요. 이렇게 하면 모든 fall through가 코드에 드러나며, 그래서 C#은 조용한 fall through를 금지합니다.

C#에서 switch 문과 switch 식의 차이는 무엇인가요?

switch 문은 문장을 실행하며 case, break, default가 필요합니다. switch 식(C# 8 이상)은 값을 만듭니다: var label = n switch { 0 => "zero", > 0 => "positive", _ => "negative" };. 모든 분기가 결과만 계산한다면 식을 쓰세요.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기