11.1 일반
패턴은 연산자(§12.14.12), switch_statement(§13.8.3), switch_expression(§12.11)에서 들어오는 데이터를 비교할 데이터의 모양을 표현하는 데 사용할 is 수 있는 구문 형식입니다. 패턴은 재귀적일 수 있으므로 데이터의 일부가 하위 패턴과 일치할 수 있습니다.
패턴은 여러 컨텍스트의 값에 대해 테스트됩니다.
- switch 문에서 사례 레이블의 패턴 은 switch 문의 식 에 대해 테스트됩니다.
- is-pattern 연산자에서 오른쪽의 패턴은 왼쪽의 식에 대해 테스트됩니다.
- switch 식에서 switch_expression_arm패턴은 switch 식의 왼쪽에 있는 식에 대해 테스트됩니다.
- 중첩 컨텍스트에서 하위 패턴 은 패턴 폼에 따라 속성, 필드 또는 다른 입력 값에서 인덱싱된 값에 대해 테스트됩니다.
패턴이 테스트되는 값을 패턴 입력 값이라고 부릅니다.
11.2 패턴 양식
11.2.1 일반
패턴에는 다음 형식 중 하나가 있을 수 있습니다.
pattern
: declaration_pattern
| constant_pattern
| var_pattern
| positional_pattern
| property_pattern
| discard_pattern
;
일부 패턴은 지역 변수의 선언을 초래할 수 있습니다.
각 패턴 양식은 패턴이 적용될 수 있는 입력 값에 대한 형식 집합을 정의합니다. 패턴 P 이 일치할이 적용됩니다. 적용할 수 없는 P경우 형식의 패턴 입력 값(§11.1)T과 일치하는 패턴 P 이 프로그램에 나타나는 경우 T 컴파일 시간 오류입니다.
예제: 다음 예제에서는 컴파일 시간 형식
vTextReader이 이므로 컴파일 시간 오류를 생성합니다. 형식TextReader의 변수는 참조와 호환되는 값을 가질 수 없습니다.stringTextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }그러나 컴파일 시간 형식
vobject은 다음과 같은 이유로 컴파일 시간 오류를 생성하지 않습니다. 형식object의 변수에는 참조와 호환되는 값이 있을 수 있습니다.stringobject v = Console.In; if (v is string s) { // code assuming v is a string }끝 예제
각 패턴 폼은 패턴 이 런타임 시 값과 일치하는 값 집합을 정의합니다.
패턴 일치 중 작업 및 부작용 평가 순서(호출 Deconstruct, 속성 액세스 및 메서드 System.ITuple호출)는 지정되지 않았습니다.
11.2.2 선언 패턴
declaration_pattern 사용하여 값에 지정된 형식이 있는지 테스트하고, 테스트가 성공하면 필요에 따라 해당 형식의 변수에 값을 제공합니다.
declaration_pattern
: type simple_designation
;
simple_designation
: discard_designation
| single_variable_designation
;
discard_designation
: '_'
;
single_variable_designation
: identifier
;
토큰 _ 이 포함된 simple_designationsingle_variable_designation 아닌 discard_designation 간주되어야 합니다.
값의 런타임 형식은 is-type 연산자(§12.14.12.1)에 지정된 것과 동일한 규칙을 사용하여 패턴의 형식에 대해 테스트됩니다. 테스트가 성공하면 패턴 이 해당 값과 일치 합니다. 형식이 nullable 값 형식 (§8.3.12) 또는 nullable 참조 형식(§8.9.3)인 경우 컴파일 시간 오류입니다. 이 패턴 형식은 값과 null 일치하지 않습니다.
참고: is-type 식
e is T과 선언 패턴e is T _은 nullable 형식이 아닌 경우T동일합니다. 끝 메모
패턴 입력 값(§11.1) e가 지정된 경우 simple_designationdiscard_designation 경우 무시(§9.2.9.2)를 표시하며 e 값은 아무것도 바인딩되지 않습니다. (이름이 _ 지정된 선언된 변수가 해당 시점에 범위에 있을 수 있지만 해당 명명된 변수는 이 컨텍스트에서 볼 수 없습니다.) 그렇지 않은 경우 simple_designation single_variable_designation 지정된 식별자가 명명한 지정된 형식의 지역 변수(§9.2.9)가 도입됩니다. 해당 지역 변수는 패턴이 값과 일치할 때 패턴 입력 값의 값이 할당됩니다.
패턴 입력 값과 지정된 형식의 정적 형식의 특정 조합은 호환되지 않는 것으로 간주되어 컴파일 시간 오류가 발생합니다. 정적 형식 E 의 값은 되는 패턴이라고 합니다. 형식 T 의 이름을 지정하는 선언 패턴은 패턴과 E 있습니다.
참고: 열린 형식에 대한 지원은 구조체 또는 클래스 형식일 수 있는 형식을 검사할 때 가장 유용할 수 있으며 boxing은 피해야 합니다. 끝 메모
예: 선언 패턴은 참조 형식의 런타임 형식 테스트를 수행하는 데 유용하며 관용구를 대체합니다.
var v = expr as Type; if (v != null) { /* code using v */ }약간 더 간결한
if (expr is Type v) { /* code using v */ }끝 예제
예: 선언 패턴을 사용하여 null 허용 형식의 값을 테스트할 수 있습니다. 형식
Nullable<T>값(또는 boxedT)은 값이 null이 아니고 null이 아니면 형식 패턴T2 id과T2T일치하거나 일부 기본 형식 또는 인터페이스와T일치합니다. 예를 들어 코드 조각에서int? x = 3; if (x is int v) { /* code using v */ }명령문
if의true조건은 런타임에 있으며 변수v는 블록 내의 형식3값을int보유합니다. 블록 후 변수v는 범위에 있지만 확실히 할당되지는 않습니다. 끝 예제
11.2.3 상수 패턴
constant_pattern 지정된 상수 값에 대해 패턴 입력 값(§11.1)의 값을 테스트하는 데 사용됩니다.
constant_pattern
: constant_expression
;
상수 패턴 P 은 있습니다T.
상수 패턴P의 경우 변환된 값은
- 패턴 입력 값의 형식이 정수 형식 또는 열거형 형식이면 패턴의 상수 값이 해당 형식으로 변환됩니다. 그렇지 않으면
- 패턴 입력 값의 형식이 정수 계열 형식 또는 열거형 형식의 nullable 버전이면 패턴의 상수 값이 기본 형식으로 변환됩니다. 그렇지 않으면
- 패턴의 상수 값 값입니다.
패턴 입력 값 e 및 변환된 값 P가 있는 상수 패턴 이 지정된 경우
- e에 정수 계열 형식 또는 열거형 형식 또는 해당 형식 중 하나의 nullable 형식이 있고 v에 정수 계열 형식이 있는 경우 패턴
P합니다. 그렇지 않으면 - 패턴
P합니다.
예: 다음 메서드의 문은
switch대/소문자 레이블에 5개의 상수 패턴을 사용합니다.static decimal GetGroupTicketPrice(int visitorCount) { switch (visitorCount) { case 1: return 12.0m; case 2: return 20.0m; case 3: return 27.0m; case 4: return 32.0m; case 0: return 0.0m; default: throw new ArgumentException(...); } }끝 예제
11.2.4 Var 패턴
var_pattern모든 값과 일치합니다. 즉, var_pattern 패턴 일치 작업은 항상 성공합니다.
var_pattern모든 형식에 적용할 수 있습니다.
var_pattern
: 'var' designation
;
designation
: simple_designation
| tuple_designation
;
tuple_designation
: '(' designations? ')'
;
designations
: designation (',' designation)*
;
패턴 입력 값(§11.1) e가 지정된 경우 지정 이 discard_designation 경우 무시(§9.2.9.2)를 표시하며 e 값은 아무것도 바인딩되지 않습니다. (해당 이름의 선언된 변수가 해당 시점에 범위에 있을 수 있지만 명명된 변수는 이 컨텍스트에서 볼 수 없습니다.) 그렇지 않으면 지정이 single_variable_designation 경우 런타임에 e의 값은 해당 형식이 e의 정적 형식이고 패턴 입력 값이 해당 지역 변수에 할당되는 해당 이름의 새로 도입된 지역 변수(§9.2.9)에 바인딩됩니다.
이름이 var var_pattern 사용되는 형식에 바인딩하는 경우 오류가 발생합니다.
지정이 tuple_designation 경우 패턴은 양식 (var 지정의 positional_pattern(§11.2.5)와 동일합니다.
) 여기서 지정은 tuple_designation 내에서 찾을 수 있습니다. 예를 들어 패턴 var (x, (y, z)) 은 .에 해당합니다 (var x, (var y, var z)).
11.2.5 위치 패턴
positional_pattern 입력 값이 아닌지 null확인하고, 적절한 Deconstruct 메서드(§12.7)를 호출하고, 결과 값에 대한 추가 패턴 일치를 수행합니다. 또한 입력 값의 형식이 포함된 Deconstruct형식과 같거나 입력 값의 형식이 튜플 형식이거나 입력 objectSystem.ITuple 값의 형식이 튜플 형식이고 식의 런타임 형식이 구현되는 경우 튜플과 유사한 패턴 구문을 지원합니다 System.ITuple.
positional_pattern
: type? '(' subpatterns? ')' property_subpattern? simple_designation?
;
subpatterns
: subpattern (',' subpattern)*
;
subpattern
: pattern
| identifier ':' pattern
;
입력 값이 패턴 형식(하위 패턴)과 일치하는 경우 형식에서 액세스 가능한 선언을 검색하고 분해 선언 Deconstruct 과 동일한 규칙을 사용하여 해당 선언 중 하나를 선택하여 메서드를 선택합니다.
positional_pattern 형식을 생략하고, 식별자가 없는 단일 하위 요소가 있고, property_subpattern 없고, simple_designation 없는 경우 오류입니다. 이는 괄호로 괄호로 constant_patternpositional_pattern 간에 구분됩니다.
목록의 패턴과 일치하는 값을 추출하려면
- 형식을 생략하고 입력 식의 형식이 튜플 형식인 경우 하위pattern의 수는 튜플의 카디널리티와 같아야 합니다. 각 튜플 요소는 해당 하위 패턴과 일치하며, 이러한 요소가 모두 성공하면 일치가 성공합니다. 하위pattern에 식별자가 있는 경우 튜플 형식의 해당 위치에 있는 튜플 요소의 이름을 지정해야 합니다.
- 그렇지 않으면 적합한
Deconstruct형식의 멤버로 존재하는 경우 입력 값의 형식이 형식과 패턴 호환되지 않는 경우 컴파일 시간 오류입니다. 런타임에 입력 값이 형식에 대해 테스트됩니다. 실패하면 위치 패턴 일치가 실패합니다. 성공하면 입력 값이 이 형식으로 변환되고Deconstruct출력 매개 변수를 수신하기 위해 새로 컴파일러에서 생성된 변수로 호출됩니다. 수신된 각 값은 해당 하위 패턴과 일치하며, 이러한 값이 모두 성공하면 일치가 성공합니다. 하위pattern에 식별자가 있는 경우 해당 위치의Deconstruct매개 변수 이름을 지정해야 합니다. - 그렇지 않은 경우 형식 을 생략하고 입력 값이 형식
object이거나 암시적 참조 변환으로System.ITuple변환할 수 있는 일부 형식이고 하위 요소 사이에 식별자가 나타나지 않으면 일치 항목이 사용됩니다System.ITuple. - 그렇지 않으면 패턴이 컴파일 시간 오류입니다.
런타임에 서브패턴이 일치하는 순서는 지정되지 않으며, 실패한 일치가 모든 하위pattern과 일치하려고 시도하지 않을 수 있습니다.
예제: 여기서는 식 결과를 분해하고 결과 값을 해당 중첩 패턴과 일치합니다.
static string Classify(Point point) => point switch { (0, 0) => "Origin", (1, 0) => "positive X basis end", (0, 1) => "positive Y basis end", _ => "Just a point", }; public readonly struct Point { public int X { get; } public int Y { get; } public Point(int x, int y) => (X, Y) = (x, y); public void Deconstruct(out int x, out int y) => (x, y) = (X, Y); }끝 예제
예: 다음과 같이 위치 패턴에서 튜플 요소 및 분해 매개 변수의 이름을 사용할 수 있습니다.
var numbers = new List<int> { 10, 20, 30 }; if (SumAndCount(numbers) is (Sum: var sum, Count: var count)) { Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}"); } static (double Sum, int Count) SumAndCount(IEnumerable<int> numbers) { int sum = 0; int count = 0; foreach (int number in numbers) { sum += number; count++; } return (sum, count); }생성된 출력은 다음과 같습니다.
Sum of [10 20 30] is 60끝 예제
11.2.6 속성 패턴
property_pattern 입력 값이 아닌지 null확인하고 액세스 가능한 속성 또는 필드를 사용하여 추출된 값과 재귀적으로 일치합니다.
property_pattern
: type? property_subpattern simple_designation?
;
property_subpattern
: '{' '}'
| '{' subpatterns ','? '}'
;
property_pattern하위 페이지에 식별자가 없는 경우 오류가 발생합니다.
형식이 nullable 값 형식 (§8.3.12) 또는 nullable 참조 형식(§8.9.3)인 경우 컴파일 시간 오류입니다.
참고: null 검사 패턴은 사소한 속성 패턴에서 제외됩니다. 문자열
s이 null이 아닌지 확인하려면 다음 형식 중 하나를 작성할 수 있습니다.#nullable enable string s = "abc"; if (s is object o) ... // o is of type object if (s is string x1) ... // x1 is of type string if (s is {} x2) ... // x2 is of type string if (s is {}) ...끝 메모 식 e와 패턴 형식
{property_pattern_list}일치하는 경우 식 e가 형식별로 지정된 T 형식과 패턴 호환되지 않는 경우 컴파일 시간 오류입니다. 형식이 없는 경우 형식은 e의 정적 형식으로 간주됩니다. property_pattern_list 왼쪽에 표시되는 각 식별자는 액세스 가능한 읽기 가능한 속성 또는 T 필드를 지정해야 합니다. property_pattern simple_designation 있으면 T 형식의 패턴 변수 를 선언합니다.
런타임 시 식은 T에 대해 테스트됩니다. 실패하면 속성 패턴 일치가 실패하고 결과는 .입니다 false. 성공하면 각 property_subpattern 필드 또는 속성이 읽혀지고 해당 값이 해당 패턴과 일치합니다. 전체 일치 false 의 결과는 이들 중 하나의 결과가 .인 경우에만 발생합니다 false. 서브패턴이 일치하는 순서는 지정되지 않으며, 실패한 일치는 런타임에 모든 하위 페턴을 테스트하지 않을 수 있습니다. 일치가 성공하고 property_pattern simple_designationsingle_variable_designation 경우 선언된 변수에 일치하는 값이 할당됩니다.
이 property_pattern 무명 형식과 패턴 일치에 사용할 수 있습니다.
예제:
var o = ...; if (o is string { Length: 5 } s) ...끝 예제
예: 다음과 같이 런타임 형식 검사 및 변수 선언을 속성 패턴에 추가할 수 있습니다.
Console.WriteLine(TakeFive("Hello, world!")); // output: Hello Console.WriteLine(TakeFive("Hi!")); // output: Hi! Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' })); // output: 12345 Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' })); // output: abc static string TakeFive(object input) => input switch { string { Length: >= 5 } s => s.Substring(0, 5), string s => s, ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()), ICollection<char> symbols => new string(symbols.ToArray()), null => throw new ArgumentNullException(nameof(input)), _ => throw new ArgumentException("Not supported input type."), };생성된 출력은 다음과 같습니다.
Hello Hi! 12345 abc끝 예제
11.2.7 무시 패턴
모든 식은 무시 패턴과 일치하므로 식 값이 삭제됩니다.
discard_pattern
: '_'
;
폼 relational_expression 패턴의 relational_expression삭제 패턴을 사용하거나 switch_labelis 패턴으로 사용하는 것은 컴파일 시간 오류입니다.
참고: 이러한 경우 식과 일치하려면 삭제
var _와 함께 var_pattern 사용합니다. 끝 메모
예제:
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday)); Console.WriteLine(GetDiscountInPercent(null)); Console.WriteLine(GetDiscountInPercent((DayOfWeek)10)); static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch { DayOfWeek.Monday => 0.5m, DayOfWeek.Tuesday => 12.5m, DayOfWeek.Wednesday => 7.5m, DayOfWeek.Thursday => 12.5m, DayOfWeek.Friday => 5.0m, DayOfWeek.Saturday => 2.5m, DayOfWeek.Sunday => 2.0m, _ => 0.0m, };생성된 출력은 다음과 같습니다.
5.0 0.0 0.0여기서 삭제 패턴은 열거형의
DayOfWeek해당 멤버가 없는 정수 값을 처리하는null데 사용됩니다. 이렇게 하면 식이switch가능한 모든 입력 값을 처리합니다. 끝 예제
11.3 패턴 하위 요소
switch 문에서 앞의 보호되지 않은 사례 집합(§13.8.3)에 의해 사례 패턴이 하위화되면 오류가 발생합니다. 비공식적으로 이는 입력 값이 이전 사례 중 하나와 일치했음을 의미합니다. 다음 규칙은 패턴 집합이 지정된 패턴을 하위로 사용하는 경우를 정의합니다.
패턴 PK합니다.
패턴 집합은 Q로 설정합니다.
-
P는 상수 패턴이며 집합Q의 모든 패턴이 '의 변환된 값과 일치P합니다. -
P은 var 패턴이고 패턴Q입력 값의 형식(§11.1)에 대해 패턴 집합이 완전하고(§11.4) 패턴 입력 값이 nullable 형식이 아니거나 일부 패턴Q이 일치null합니다. -
P는 형식T이 있는 선언 패턴이며 패턴Q집합은 합니다(T).
11.4 패턴 완전성
비공식적으로, null 이외의 해당 형식의 가능한 모든 값에 대해 집합의 일부 패턴을 적용할 수 있는 경우 형식에 대해 패턴 집합이 완전합니다. 다음 규칙은 패턴 집합이 형식에 대해 완전할 때를 정의합니다.
다음 조건이 있는 경우 형식 Q 에 대해 패턴 T합니다.
-
T은 정수 또는 열거형 형식이거나 그 중 하나의 nullable 버전이며, nullable이 아닌 기본 형식의T가능한 모든 값에Q대해 일부 패턴이 해당 값과 일치합니다. - 일부 패턴
Q은 var 패턴입니다. - 일부 패턴은 형식에
Q대한 선언 패턴
예제:
static void M(byte b) { switch (b) { case 0: case 1: case 2: ... // handle every specific value of byte break; // error: the pattern 'byte other' is subsumed by the (exhaustive) // previous cases case byte other: break; } }끝 예제
ECMA C# draft specification