숏컷 코드
// and / or / not 조합
string category = score switch
{
>= 90 and <= 100 => "S",
>= 70 and < 90 => "A",
>= 50 and < 70 => "B",
< 0 or > 100 => throw new ArgumentOutOfRangeException(),
_ => "F"
};
// list pattern (C# 11+)
string describe = items switch
{
[] => "비어있음",
[var single] => $"하나: {single}",
[var first, ..] => $"첫 번째: {first}, 이후 더 있음"
};문법
and / or / not — 패턴 조합
and, or, not으로 여러 패턴을 조합합니다. 산술 연산자처럼 쓰이지만 패턴 연산자입니다.
// and — 두 조건 모두 만족
bool isValidAge = age is >= 0 and <= 150;
// or — 하나라도 만족
bool isWeekend = day is DayOfWeek.Saturday or DayOfWeek.Sunday;
// not — 조건 반전
bool isNotNull = value is not null;
bool isNotEmpty = items is not [];
// 복합 조합
string label = (x, y) switch
{
( > 0, > 0) => "1사분면",
( < 0, > 0) => "2사분면",
( < 0, < 0) => "3사분면",
( > 0, < 0) => "4사분면",
_ => "축 위"
};property pattern — 중첩 객체 분기
{ Property: pattern } 형태로 객체의 속성을 패턴으로 검사합니다. 중첩 객체도 .으로 접근해 한 번에 처리할 수 있습니다.
// 단순 property pattern
string describe = user switch
{
{ IsAdmin: true, Name: not null } => $"관리자: {user.Name}",
{ IsActive: false } => "비활성 사용자",
_ => "일반 사용자"
};
// 중첩 property pattern
decimal discount = order switch
{
{ Customer.IsPremium: true, Total: > 100_000 } => order.Total * 0.15m,
{ Customer.IsPremium: true } => order.Total * 0.10m,
{ Total: > 50_000 } => order.Total * 0.05m,
_ => 0m
};positional pattern — 분해 가능한 타입
Deconstruct를 구현하는 타입이나 튜플에서 위치 기반으로 패턴을 적용합니다.
// 튜플 positional pattern
string quadrant = (x, y) switch
{
(0, 0) => "원점",
( > 0, > 0) => "1사분면",
( <= 0, > 0) => "2사분면",
_ => "기타"
};
// record positional pattern (record는 Deconstruct 자동 생성)
record Point(int X, int Y);
string classify = point switch
{
Point(0, 0) => "원점",
Point(var x, 0) => $"X축: {x}",
Point(0, var y) => $"Y축: {y}",
Point(var x, var y) when x == y => "대각선",
_ => "일반 위치"
};list pattern (C# 11+) — 시퀀스 구조 분기
list pattern은 배열이나 리스트의 구조(길이, 특정 위치의 값)를 기준으로 분기합니다.
int[] scores = { 90, 85, 70 };
string result = scores switch
{
[] => "점수 없음",
[var only] => $"한 명: {only}",
[var first, var last] => $"두 명: {first}, {last}",
[var first, .., var last] => $"다수 — 처음: {first}, 마지막: {last}",
};
// 명령 파싱에서 유용
string[] args = { "move", "10", "20" };
string cmd = args switch
{
["move", var x, var y] => $"이동: ({x}, {y})",
["shoot", var target] => $"사격: {target}",
["quit"] => "종료",
_ => "알 수 없는 명령"
};..은 슬라이스 패턴으로 나머지 요소들과 매칭합니다.
체크포인트
| 패턴 | 예시 | 잘 맞는 상황 |
|---|---|---|
and / or / not | >= 0 and < 100 | 범위 조합, 복합 조건 |
| property pattern | { Name: not null } | 객체 속성 기반 분기 |
| 중첩 property pattern | { Order.Total: > 0 } | 깊은 구조 한 번에 분기 |
| positional pattern | (x, y) / Point(var x, _) | 튜플, record 분해 |
| list pattern | [first, .., last] | 시퀀스 구조 분기, 파서 |
주의할 점
패턴 하나에 규칙을 너무 많이 밀어 넣으면 짧아 보여도 해석이 어렵습니다. and/or가 3개 이상 중첩되거나 property pattern이 깊어지면 보조 메서드로 분리하는 편이 좋습니다.
switch expression의 arm 순서가 중요합니다. 컴파일러는 위에서 아래로 평가하다가 처음 일치하는 arm에서 멈춥니다. 좁은(구체적인) 조건을 먼저, _ 와일드카드를 마지막에 배치하세요.
참고 링크
1 sources