11 パターンとパターン マッチング
11.1 全般
pattern は構文形式であり、is
演算子 (§12.12.12) とswitch_statement (§13.8.3) で使用して、受信データの比較対象となるデータの形状を表すことができます。 パターンは、switch ステートメントの式に対して、またはis
演算子の左側にあるrelational_expressionに対してテストされ、それぞれがパターン入力値と呼ばれます。
11.2 パターン形式
11.2.1 全般
パターンには、次のいずれかの形式があります。
pattern
: declaration_pattern
| constant_pattern
| var_pattern
;
declaration_patternとvar_patternにより、ローカル変数が宣言される可能性があります。
各パターン フォームは、パターンを適用できる入力値の型のセットを定義します。 パターン P
はパターンが一致する可能性のある値を持つ型の中にT
がある場合にT
型に適用できます。 P
がT
に適用できない場合、パターンP
がT
型のパターン入力値 (§11.1) と一致するようにプログラムに表示される場合、コンパイル時エラーになります。
例: 次の例では、
v
のコンパイル時の型がTextReader
されているため、コンパイル時エラーが生成されます。TextReader
型の変数は、string
と参照互換の値を持つことはありません。TextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }
ただし、
v
のコンパイル時の型がobject
されているため、次のコードではコンパイル時エラーは生成されません。object
型の変数は、string
と参照互換の値を持つことができます。object v = Console.In; if (v is string s) { // code assuming v is a string }
end の例
各パターン フォームは、パターンが実行時に値 照合 値のセットを定義します。
11.2.2 宣言パターン
declaration_patternは、値に特定の型があることをテストするために使用され、テストが成功した場合は、その型の変数に値を指定します。
declaration_pattern
: type simple_designation
;
simple_designation
: single_variable_designation
;
single_variable_designation
: identifier
;
値のランタイム型は、is-type 演算子 (§12.12.12.1) で指定されたのと同じ規則を使用して、パターン内の type に対してテストされます。 テストが成功すると、その値パターン照合されます。 type が null 許容値型 (§8.3.12) の場合、コンパイル時エラーです。 このパターン フォームは、 null
値と一致しません。
注: is-type 式
e is T
と宣言パターンe is T _
は、T
が null 許容型でない場合と同等です。 end note
パターン入力値 (§11.1) eを指定すると simple_designation が 識別子である場合 _
破棄 (§9.2.9.1) を表し、 e の値は何にもバインドされません。 ( _
という名前の宣言された変数は、その時点でスコープ内にある場合がありますが、その名前付き変数はこのコンテキストでは表示されません)。 simple_designation が他の識別子である場合は、指定された識別子によって指定された型のローカル変数 (§9.2.9) が導入されます。 そのローカル変数には、パターンが マッチしたときに、その値 パターン入力値の値が割り当てられます。
パターン入力値と特定の型の静的型の特定の組み合わせは互換性がないとみなされ、コンパイル時エラーが発生します。 静的型E
の値は、id 変換、暗黙的または明示的な参照変換、ボックス化変換、E
からT
へのボックス化解除の変換、またはE
またはT
のいずれかが開いている型 (§8.4.3) がある場合に型とT
互換性があると言われます。 T
型に名前を付ける宣言パターンはE
がT
と互換性のあるすべての型E
に適用できます。
注: オープン型のサポートは、構造体型またはクラス型である可能性がある型をチェックする場合に最も役立ち、ボックス化は避ける必要があります。 end note
例: 宣言パターンは、参照型の実行時の型テストを実行するのに役立ち、イディオムを置き換えます
var v = expr as Type; if (v != null) { /* code using v */ }
少し簡潔に
if (expr is Type v) { /* code using v */ }
end の例
typeが null 許容値型の場合はエラーです。
例: 宣言パターンは、null 許容型の値をテストするために使用できます。型
Nullable<T>
(またはボックス化されたT
) の値は、値が null 以外でT2 id
T2
がT
場合、またはT
の基本型またはインターフェイスの型パターンと一致します。 たとえば、コード フラグメント内int? x = 3; if (x is int v) { /* code using v */ }
if
ステートメントの条件は実行時にtrue
され、変数v
はブロック内でint
型の値3
を保持します。 end の例
11.2.3 定数パターン
constant_patternは、パターン入力値 (§11.1) の値を特定の定数値に対してテストするために使用されます。
constant_pattern
: constant_expression
;
定数パターンP
P
の定数式から型T
への暗黙的な変換がある場合、型T
に適用できます。
定数パターン P
の場合、その 変換された値 は
- パターン入力値の型が整数型または列挙型の場合、パターンの定数値はその型に変換されます。然も無くば
- パターン入力値の型が整数型または列挙型の null 許容バージョンである場合、パターンの定数値は基になる型に変換されます。然も無くば
- パターンの定数値の値。
パターン入力値がe変換された値を持つ定数パターンP
v、
- eが整数型または列挙型、またはいずれかの null 許容形式を持ち、v が整数型を持つ場合、パターン
P
マッチ式e == v
の結果がtrue
場合は値e。それ以外の場合 object.Equals(e, v)
がtrue
を返す場合はパターン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(...); } }
end の例
11.2.4 Var パターン
var_pattern matchesすべての値。 つまり、 var_pattern を使用したパターン マッチング操作は常に成功します。
var_patternはすべての型に適用できます。
var_pattern
: 'var' designation
;
designation
: simple_designation
;
パターン入力値 (§11.1) eを指定すると デザイン が 識別子 _
の場合、破棄 (§9.2.9.1) を示し、 e の値は何にもバインドされません。 (その名前を持つ宣言された変数は、その時点でスコープ内にある場合がありますが、このコンテキストではその名前付き変数は表示されません)。 designation が他の識別子である場合、実行時に e の値はその名前の新しく導入されたローカル変数 (§9.2.9) にバインドされ、その型は e の静的な型であり、パターン入力値はそのローカル変数に割り当てられます。
var_patternが使用されている型にvar
名前がバインドされると、エラーになります。
11.3 パターンのサブ再開
switch ステートメントでは、前の一連の非ガード ケース (§13.8.3) によって、ケースのパターンがsubsumed場合はエラーになります。 非公式には、これは、入力値が前のいずれかのケースで一致したことを意味します。 次の規則は、一連のパターンが特定のパターンをサブスムするタイミングを定義します。
パターンが一致P
そのパターンのランタイム動作の仕様がK
に一致P
場合は定数K
。
一連のパターン Q
subsumes 次のいずれかの条件が満たされている場合に P
パターンです。
P
は定数パターンであり、セットQ
内のすべてのパターンがP
の 変換された値と一致しますP
は var パターンであり、パターン入力値の型 (§11.1) に対してQ
パターンのセットが exhaustive (§11.4) であり、パターン入力値が null 許容型でないか、Q
のパターンがnull
に一致します。P
は型T
を持つ宣言パターンであり、型T
(§11.4) に対してQ
パターンのセットがです。
11.4 パターンの網羅性
非公式には、null 以外の型のすべての可能な値に対して、セット内のパターンが適用される場合、パターンのセットは完全です。 次の規則は、一連のパターンが型に対していつ 完全 するかを定義します。
次のいずれかの条件が満たされている場合、型T
Q
一連のパターンは完全です。
T
は整数型または列挙型、またはいずれかの null 許容バージョンであり、T
の null 非許容基になる型のすべての可能な値に対して、Q
のパターンはその値と一致します。Q
の一部のパターンは、var パターン; またはQ
のパターンの中には、型D
の宣言パターンがあり、ID 変換、暗黙的な参照変換、またはT
からD
へのボックス化変換があります。
例:
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; } }
end の例
ECMA C# draft specification