Menu

C# switch 식: 문법, 패턴, 무시 항목 _, when

C# 8의 switch 식은 case와 break 대신 패턴 갈래로 값을 결과로 바꿉니다. 문법, _ 무시 항목, 속성/튜플/관계 패턴, and/or/not, when 가드, 완전성 경고와 SwitchExpressionException을 실행 가능한 C# 7 대응 코드와 함께 알아봅니다.

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

switch 식은 입력 값을 결과로 대응시킵니다. C# 8에서 추가되었으며, 모든 case가 무언가를 반환하거나 대입하기만 하는 switch 문이라는 흔한 패턴을 대체합니다:

// C# 8 and later
string StatusText(int code) => code switch
{
    200 => "OK",
    301 or 302 => "Redirect",   // 'or' needs C# 9
    404 => "Not Found",
    >= 500 => "Server Error",   // relational patterns need C# 9
    _ => "Unknown"
};

위에서 아래로 읽습니다. switch 앞의 값을 각 갈래와 순서대로 검사하고, 패턴이 처음 일치하는 갈래가 결과를 내놓습니다. case도, break도, default 키워드도 없습니다. _(무시 패턴)는 무엇이든 일치하며 기본값 역할을 합니다.

C# 7에서는 같은 대응을 작은 메서드 안의 switch 문으로, case마다 return을 써서 만듭니다:

출력:

200 OK
302 Redirect
404 Not Found
503 Server Error
418 Unknown

식 형태가 더 짧은 주된 이유는 갈래가 한 줄씩이고 메서드 본문이 사라지기 때문입니다. 또 식이므로 인수, 보간 구멍, return, 필드 이니셜라이저 등 값이 들어갈 수 있는 곳이면 어디든 둘 수 있습니다.

문법 규칙

var result = input switch
{
    pattern1 => value1,
    pattern2 when condition => value2,
    _ => fallback
};
  • 입력이 먼저 오고 그다음이 switch입니다. 문 형태와 반대입니다.
  • 각 갈래는 pattern => expression입니다. 오른쪽은 식 하나여야 하며, 로직이 더 필요하면 메서드를 호출하세요.
  • 갈래는 쉼표로 구분합니다. 마지막 갈래 뒤의 쉼표도 허용됩니다.
  • 전체가 식이므로, 이를 쓰는 문장은 닫는 중괄호 뒤에 ;로 끝납니다.
  • 모든 갈래는 공통 타입의 값을 만들어야 합니다. var x = n switch { 0 => "zero", _ => 0 };은 컴파일되지 않습니다(CS8506, 최적의 타입 없음). C# 9부터는 선언된 대상 타입이 이를 해결합니다: object x = n switch { 0 => "zero", _ => 0 };은 컴파일됩니다.
  • 모든 갈래가 값을 만들어야 하므로, 갈래에서 Console.WriteLine 같은 void 메서드를 호출할 수 없고, switch 식은 단독 문장이 될 수 없습니다(CS0201). 동작에는 switch 문을 쓰세요.
  • 갈래는 값을 만드는 대신 예외를 던질 수 있습니다: _ => throw new ArgumentOutOfRangeException(nameof(input)).
  • 앞의 갈래가 이미 모두 덮어서 도달할 수 없는 갈래는 오류 CS8510 The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.로 거부됩니다. 구체적인 갈래를 일반적인 갈래보다 앞에 두세요.

관계 패턴과 논리 패턴(C# 9)

C# 9는 <, <=, >, >=를 패턴으로, and, or, not을 조합자로 추가했습니다. 범위 표가 명세서처럼 읽힙니다:

// C# 9 and later
string Grade(int score) => score switch
{
    < 0 or > 100 => throw new ArgumentOutOfRangeException(nameof(score)),
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    >= 60 => "D",
    _ => "F"
};

string AgeGroup(int age) => age switch
{
    < 13 => "child",
    >= 13 and <= 19 => "teen",
    _ => "adult"
};

bool IsLetter(char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';

갈래는 순서대로 시도되므로 >= 80은 90 미만의 점수만 봅니다. 관계 패턴은 오른쪽에 상수만 받으므로, 변수와 비교하려면 when 가드를 쓰세요. 범위 표의 C# 7 대응은 if 체인입니다:

출력:

95 -> A
83 -> B
71 -> C
64 -> D
12 -> F

not은 대부분 not null로 쓰입니다: x is not null, 또는 갈래 not null => x.Name.

속성 패턴

속성 패턴은 객체의 멤버로 일치 여부를 봅니다: { Property: pattern, ... }. switch 식과 함께 쓰면 && 조건의 체인 없이 비즈니스 규칙을 표현할 수 있습니다:

// C# 8 and later
decimal ShippingCost(Order order) => order switch
{
    { Total: >= 100m } => 0m,                       // relational inside: C# 9
    { Country: "US", Express: true } => 15m,
    { Country: "US" } => 5m,
    { Express: true } => 30m,
    null => throw new ArgumentNullException(nameof(order)),
    _ => 12m
};

나열한 모든 속성이 일치해야 갈래가 일치합니다. 빈 속성 패턴 { }은 null이 아닌 모든 값과 일치합니다. C# 10은 중첩 멤버를 위한 확장 속성 패턴을 추가했습니다: { Customer: { Address: { Country: "US" } } } 대신 { Customer.Address.Country: "US" }.

튜플 패턴

튜플로 switch하면 여러 값을 한꺼번에 일치시킬 수 있으며, 결정 표를 깔끔하게 표현하는 방법입니다:

// C# 9 and later (the 'or' pattern)
string Winner(string a, string b) => (a, b) switch
{
    ("rock", "scissors") or ("scissors", "paper") or ("paper", "rock") => "player 1",
    var (x, y) when x == y => "draw",
    _ => "player 2"
};

var (x, y)는 튜플을 when 가드가 비교할 수 있는 두 변수로 분해합니다. C# 7에서는 보통 값들을 하나의 키로 합치거나 결과 딕셔너리를 써서 대신합니다:

출력:

player 1
player 2
draw

타입 패턴과 when

갈래는 실행 시점 타입을 검사하고 변수를 바인딩할 수 있으며, when 절은 패턴 문법으로 표현할 수 없는 어떤 조건이든 덧붙입니다:

// C# 8 and later
double Area(Shape shape) => shape switch
{
    Circle c => Math.PI * c.Radius * c.Radius,
    Rectangle r when r.Width == r.Height => r.Width * r.Width,
    Rectangle r => r.Width * r.Height,
    null => throw new ArgumentNullException(nameof(shape)),
    _ => throw new NotSupportedException(shape.GetType().Name)
};

C# 7 버전은 if 체인 안에서 is 타입 패턴을 쓰며, 같은 방식으로 변수를 바인딩합니다:

출력:

Circle: 12.57
Rectangle: 13.50

완전성과 SwitchExpressionException

switch 식은 모든 입력에 대해 값을 만들어야 합니다. 어떤 갈래와도 일치하지 않는 입력을 컴파일러가 발견하면 경고합니다:

warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '0' is not covered.

오류가 아니라 경고이므로 코드는 여전히 빌드됩니다. 실행 시점에 일치하지 않는 값이 오면 식은 System.Runtime.CompilerServices.SwitchExpressionException을 던지며, 메시지는 일치하지 않은 값으로 끝납니다(Unmatched value was 3.).

열거형은 특별한 경우입니다. 이름 붙은 모든 멤버에 갈래가 있어도 열거형 변수는 어떤 정수든 담을 수 있으므로((Size)3), 컴파일러는 "이름 없는 열거형 값"에 대해 CS8524를 보고합니다:

// C# 8 and later
enum Size { Small, Medium, Large }

string Code(Size s) => s switch
{
    Size.Small => "S",
    Size.Medium => "M",
    Size.Large => "L",
    // warning CS8524 without the next arm
    _ => throw new ArgumentOutOfRangeException(nameof(s))
};

유용한 예외를 던지는 명시적 _ 갈래를 추가하세요. 가정을 문서화하고, 경고를 없애고, 잘못된 값이 나타났을 때 SwitchExpressionException보다 명확한 오류를 줍니다.

대안으로서의 Dictionary

갈래가 순수한 상수와 값의 쌍이고 표가 커지거나 설정에서 올 수 있다면, Dictionary가 모든 C# 버전에서 같은 일을 하며 실행 시점에 만들 수도 있습니다:

출력:

19.00
11.50
0

알 수 없는 나라는 세율 0m을 받습니다. decimal 곱은 두 피연산자의 소수 자릿수를 합친 만큼의 소수 자리를 가지므로, 100m * 0.19m은 19.00으로, 세율 0은 0으로 출력됩니다.

switch 식과 switch 문

switch 문switch 식
도입 시기C# 1C# 8
값을 만드는가아니요예
분기별 문법case X: ... break;X => value,
기본값default:_ =>
분기당 여러 문장가능불가, 메서드를 호출
완전성 경고없음있음(CS8509)
실행 시점에 일치 없음아무것도 실행 안 됨SwitchExpressionException

두 형태는 같은 패턴(타입, 상수, 속성, 튜플, 관계)을 받으므로 하나를 배우면 다른 하나도 익히게 됩니다. 선택은 모양의 문제입니다. 값은 식으로, 일련의 동작은 문으로 처리합니다.

자주 묻는 질문

C#의 switch 식이란 무엇인가요?

C# 8에서 추가된 switch 식은 값으로 평가됩니다: string text = code switch { 200 => "OK", 404 => "Not Found", _ => "Unknown" };. 입력은 switch 키워드 앞에 오고, 각 갈래는 pattern => result이며, 갈래는 쉼표로 구분하고, case, break, default 키워드는 없습니다.

C# switch 식의 default case는 무엇인가요?

무시 패턴 _는 무엇이든 일치하므로, 마지막 갈래 _ => "Unknown"이 default 역할을 합니다. 모든 것을 받는 갈래가 없으면 다뤄지지 않는 입력이 있을 때 컴파일러가 경고(CS8509)하고, 실행 시점에 일치하지 않는 값은 SwitchExpressionException을 던집니다.

switch 식의 한 갈래에서 여러 값을 일치시키려면 어떻게 하나요?

C# 9의 or 패턴을 쓰세요: "sat" or "sun" => "weekend". 범위에는 관계 패턴을 and로 조합합니다: >= 13 and <= 19 => "teen". C# 8에서는 결과가 같은 갈래를 값마다 따로 나열합니다.

C# switch 식에서 when을 쓸 수 있나요?

네. 갈래는 패턴 뒤에 가드를 붙일 수 있습니다: Order o when o.Total > 100 => 0m. 패턴이 일치하고 when 조건이 참일 때만 그 갈래가 일치하며, 아니면 다음 갈래로 평가가 이어집니다.

switch 식과 switch 문 중 무엇을 써야 하나요?

상태를 레이블로 바꾸거나 가격을 계산할 때처럼 모든 분기가 값만 만든다면 식을 쓰세요. 분기가 여러 문장을 실행하거나, 부수 효과가 있거나, 루프를 빠져나가야 한다면 문을 쓰세요. 식은 문에는 없는 완전성 경고도 줍니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기