11 パターンとパターン マッチング

11.1 全般

パターンは構文形式であり、is演算子 (§12.15.12)、switch_statement (§13.8.3)、およびswitch_expression (§12.12) で使用して、受信データの比較対象となるデータの形状を表すことができます。 データの一部を サブパターンと照合できるように、パターンは再帰的な場合があります。

パターンは、さまざまなコンテキストの値に対してテストされます。

  • switch ステートメントでは、ケース ラベルの パターン が switch ステートメントの に対してテストされます。
  • is-pattern 演算子では、右側のパターンが左側の式に対してテストされます。
  • switch 式では、switch_expression_armパターンが switch 式の左側の式に対してテストされます。
  • 入れ子になったコンテキストでは、 サブパターンは、 パターンの形式に応じて、プロパティ、フィールド、または他の入力値から取得された値に対してテストされます。

パターンがテストされる値を パターン入力値と呼ばれます。

11.2 パターン形式

11.2.1 全般

パターンには、次のいずれかの形式があります。

pattern
    : logical_pattern
    ;

primary_pattern
    : parenthesized_pattern
    | declaration_pattern
    | constant_pattern
    | var_pattern
    | positional_pattern
    | property_pattern
    | discard_pattern
    | type_pattern
    | relational_pattern
    ;

parenthesized_pattern
    : '(' pattern ')'
    ;

'(' pattern ')'実稼働では、パターンをかっこで囲んで、logical_patternのいずれかを使用して組み合わせたパターン間の評価順序を適用できます。

一部の パターンs では、ローカル変数が宣言される可能性があります。

各パターン フォームは、パターンを適用できる入力値の型のセットを定義します。 パターン Pパターンが一致する可能性のある値を持つ型の中にTがある場合にT型に適用できます。 Pに適用できない場合、パターンTP型のパターン入力値 (T) と一致するようにプログラムに表示される場合、コンパイル時エラーになります。

: 次の例では、 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 の例

各パターン フォームは、パターンが実行時に値 照合 値のセットを定義します。

パターン マッチング中の操作と副作用の評価順序 ( 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_designationは、_見なされます

値のランタイム型は、is-type 演算子 (§12.15.12.1) で指定されたのと同じ規則を使用して、パターン内のに対してテストされます。 テストが成功すると、その値パターン照合されます。 型が null 許容値 (§8.3.12) または null 許容参照型 (§8.9.3) の場合、コンパイル時エラーです。 このパターン フォームは、 null 値と一致しません。

: is-type 式 e is T と宣言パターン e is T _ は、 T が null 許容型でない場合と同等です。 注釈

パターン入力値 (§11.1) e を指定すると、 simple_designationdiscard_designation場合は破棄 (§9.2.9.2) を表し、 e の値は何にもバインドされません。 ( _ という名前の宣言された変数は、その時点でスコープ内にある場合がありますが、その名前付き変数はこのコンテキストでは表示されません)。それ以外の場合、 simple_designationsingle_variable_designationされている場合は、指定された識別子によって指定された型のローカル変数 (§9.2.9) が導入されます。 そのローカル変数には、パターンが マッチしたときに、その値 パターン入力値の値が割り当てられます。

パターン入力値と特定の型の静的型の特定の組み合わせは互換性がないとみなされ、コンパイル時エラーが発生します。 静的型Eの値は、id 変換、暗黙的または明示的な参照変換、ボックス化変換、ボックス化解除変換、またはからへの暗黙的または明示的な null 許容値の型変換、またはTまたはEのいずれかがオープン型 (T) である場合、E型とTがあると言われます。 T型に名前を付ける宣言パターンはEEと互換性のあるすべての型Tに適用できます。

: オープン型のサポートは、構造体型またはクラス型である可能性がある型をチェックする場合に最も役立ち、ボックス化は避ける必要があります。 注釈

: 宣言パターンは、参照型の実行時の型テストを実行するのに役立ち、イディオムを置き換えます

var v = expr as Type;
if (v != null) { /* code using v */ }

少し簡潔に

if (expr is Type v) { /* code using v */ }

end の例

: 宣言パターンは、null 許容型の値をテストするために使用できます。型Nullable<T> (またはボックス化されたT) の値は、値が null 以外で T2 idT2T場合、またはTの基本型またはインターフェイスの型パターンと一致します。 たとえば、コード フラグメント内

int? x = 3;
if (x is int v) { /* code using v */ }

if ステートメントの条件は実行時にtrueされ、変数vはブロック内で3型の値intを保持します。 ブロックの後、変数 v はスコープ内にありますが、確実には割り当てません。 end の例

11.2.3 定数パターン

constant_patternは、パターン入力値 (§11.1) の値を特定の定数値に対してテストするために使用されます。

constant_pattern
    : constant_expression
    ;

定数パターンPTの定数式から型Pへの暗黙的な変換がある場合、型Tに適用できます。

定数パターン Pの場合、その 変換された値

  • パターン入力値の型が整数型または列挙型の場合、パターンの定数値はその型に変換されます。然も無くば
  • パターン入力値の型が整数型または列挙型の null 許容バージョンである場合、パターンの定数値は基になる型に変換されます。然も無くば
  • パターンの定数値の値。

パターン入力値がe変換された値を持つ定数パターンPv

  • eが整数型または列挙型、またはいずれかの null 許容形式を持ち、v が整数型を持つ場合、パターンPマッチの結果が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_patternmatchesすべての値。 つまり、 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 の値は、その名前の新しく導入されたローカル変数 (§9.2.9) にバインドされ、その型は e の静的型であり、パターン入力値はそのローカル変数に割り当てられます。

varが使用されている型に名前がバインドされると、エラーになります。

指定tuple_designationの場合、パターンはフォーム デザイン(var (§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を含む型と同じ場合、または入力値の型がタプル型の場合、または入力値の型が object または System.ITuple であり、式のランタイム型が System.ITuple実装されている場合は、タプルに似たパターン構文 (型が指定されていない) もサポートされます。

positional_pattern
    : type? '(' subpatterns? ')' property_subpattern? simple_designation?
    ;
subpatterns
    : subpattern (',' subpattern)*
    ;
subpattern
    : pattern
    | identifier ':' pattern
    ;

入力値がパターン (subpatterns)に一致する場合、メソッドを選択するには、 Deconstruct のアクセス可能な宣言を検索し、分解宣言と同じ規則を使用してそのうちの 1 つを選択します。 positional_patternが型を省略し、識別子のない単一のサブパターンを持ち、property_subpatternがなく、simple_designationがない場合はエラーです。 これにより、親子化された constant_patternpositional_patternの間であいまいさが解消されます。 リスト内のパターンと一致する値を抽出するには、

  • が省略され、入力式の型がタプル型の場合、サブパターンの数はタプルのカーディナリティと同じになります。 各タプル要素は対応する サブパターンと照合され、これらすべてが成功した場合は一致が成功します。 サブパターン識別子がある場合は、タプル型の対応する位置にタプル要素の名前を付けます。
  • それ以外の場合、適切なDeconstructが型のメンバーとして存在する場合、入力値の型が型とパターン互換でない場合はコンパイル時エラーになります。 実行時に、入力値は に対してテストされます。 これが失敗した場合、位置指定パターンの一致は失敗します。 成功した場合、入力値はこの型に変換され、 Deconstruct はコンパイラによって生成された新しい変数を使用して呼び出され、出力パラメーターを受け取ります。 受信した各値は対応する サブパターンと照合され、これらすべてが成功した場合は一致が成功します。 サブパターン識別子がある場合は、Deconstructの対応する位置にパラメーターの名前を付けます。
  • それ以外の場合、 が省略され、入力値が object 型または暗黙的な参照変換によって System.ITuple に変換できる型であり、サブパターン間に 識別子 が表示されない場合、一致では System.ITupleが使用されます。
  • それ以外の場合、パターンはコンパイル時エラーです。

実行時にサブパターンが一致する順序は指定されておらず、一致が失敗してもすべてのサブパターンとの一致が試行されない場合があります。

: ここでは、式の結果を分解し、結果の値を対応する入れ子になったパターンと照合します。

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);
}

end の例

: タプル要素と分解パラメーターの名前は、次のように位置指定パターンで使用できます。

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

end の例

11.2.6 プロパティ パターン

property_patternは、入力値がnullされていないことを確認し、アクセス可能なプロパティまたはフィールドを使用して抽出された値と再帰的に一致します。

property_pattern
    : type? property_subpattern simple_designation?
    ;
property_subpattern
    : '{' '}'
    | '{' subpatterns ','? '}'
    ;

property_patternサブパターン識別子が含まれていない場合はエラーです。

型が null 許容値 (§8.3.12) または null 許容参照型 (§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 がパターン{subpatterns}に一致すると、式 e型で指定された型 T とパターン互換でない場合、コンパイル時エラーになります。 型が存在しない場合、型は e の静的型であると見なされます。 サブパターンの左側に表示される各識別子は、アクセス可能な読み取り可能なプロパティまたは T フィールドを指定する必要があります。property_patternsimple_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) ...

end の例

: 次のように、実行時の型チェックと変数宣言をプロパティ パターンに追加できます。

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

end の例

11.2.7 破棄パターン

すべての式が破棄パターンと一致し、その結果、式の値が破棄されます。

discard_pattern
    : '_'
    ;

フォームのrelational_expressionisrelational_expressionまたはswitch_labelのパターンとして破棄パターンを使用するのは、コンパイル時エラーです。

: そのような場合は、任意の式と一致させるために、破棄を使用します。 注釈

例:

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

ここでは、破棄パターンを使用して、 null と、 DayOfWeek 列挙体の対応するメンバーを持たない整数値を処理します。 これにより、 switch 式が使用可能なすべての入力値を処理することが保証されます。 end の例

11.2.8 型パターン

type_patternは、パターン入力値 (§11.1) に特定の型があることをテストするために使用されます。

type_pattern
    : type
    ;

Tに名前を付ける型パターンは、ET (§11.2.2) と互換性のあるすべての型E適用されます。

値のランタイム型は、is-type 演算子 (§12.15.12.1) で指定されたのと同じ規則を使用して型に対してテストされます。 テストが成功した場合、パターンはその値と一致します。 型が null 許容 の場合はコンパイル時エラーです。 このパターン フォームは、 null 値と一致しません。

11.2.9 リレーショナル パターン

relational_patternは、パターン入力値 (§11.1) を定数値に対してリレーショナルにテストするために使用されます。

relational_pattern
    : '<'  relational_expression
    | '<=' relational_expression
    | '>'  relational_expression
    | '>=' relational_expression
    ;

定数値に評価するには、relational_pattern内のrelational_expressionが必要です。

リレーショナル パターンは、関係演算子の<をサポートします。 sbytebyteshortushortintuintlongulongcharfloatdoubledecimalnintnuint、列挙型の両方のオペランドを使用して、このような二項関係演算子をサポートするすべての組み込み型に<=>、および>=します。

relational_patternは、適切な組み込みの二項関係演算子が型Tの両方のオペランドで定義されている場合、または明示的な null 許容変換またはボックス化解除変換がTから定数式の型に存在する場合に、型T適用できます。

式が double.NaNfloat.NaN、または null 定数と評価された場合、コンパイル時エラーになります。

入力値に、適切な組み込みの二項関係演算子が定義されている型がある場合、その演算子の評価はリレーショナル パターンの意味と見なされます。 それ以外の場合、明示的な null 許容変換またはボックス化解除変換を使用して、入力値が定数式の型に変換されます。 そのような変換が存在しない場合、コンパイル時エラーとなります。 変換が失敗した場合、パターンは一致しないと見なされます。 変換が成功した場合、パターン マッチング操作の結果は、変換された入力 e «op» v 式を評価した結果です。ここで、 e は変換された入力、«op» は関係演算子、 v は定数式です。

例:

Console.WriteLine(Classify(13));
Console.WriteLine(Classify(double.NaN));
Console.WriteLine(Classify(2.4));

static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};

生成される出力は次のとおりです。

Too high
Unknown
Acceptable

end の例

11.2.10 論理パターン

logical_patternは、パターン一致の結果を否定したり、結合 (and) または結合 (or) を使用して複数のパターン一致の結果を結合したりするために使用されます。

logical_pattern
    : disjunctive_pattern
    ;

disjunctive_pattern
    : disjunctive_pattern 'or' conjunctive_pattern
    | conjunctive_pattern
    ;

conjunctive_pattern
    : conjunctive_pattern 'and' negated_pattern
    | negated_pattern
    ;

negated_pattern
    : 'not' negated_pattern
    | primary_pattern
    ;

notand、および or は、まとめて パターン演算子と呼ばれます。

negated_patternは、否定されるパターンが一致しない場合に一致し、その逆も一致します。 conjunctive_patternでは、両方のパターンが一致する必要があります。 disjunctive_patternには、いずれかのパターンが一致する必要があります。 対応する言語演算子、 &&||とは異なり、 andor はショートサーキット演算子 ではありません

これは、パターン変数が not または or パターン演算子の下で宣言されるコンパイル時エラーです。

: notor もパターン変数に対して明確な代入を生成できないため、これらの位置で宣言するのはエラーです。 注釈

conjunctive_patternでは、2 番目のパターンの入力型は、andの最初のパターンの型縮小要件によって絞り込まれます。 パターン P狭い型は、次のように定義されます。

  • Pが型パターンの場合、縮小された型は型パターンの型です。
  • それ以外の場合、 P が宣言パターンの場合、 縮小された型 は宣言パターンの型です。
  • それ以外の場合、 P が明示的な型を提供する再帰パターンである場合、 縮小された型はその型 になります。
  • それ以外の場合、Pがpositional_pattern (§11.2.5) のITupleの規則を使用して照合される場合、縮小された型は型System.ITupleです。
  • それ以外の場合、Pが定数が null 定数ではなく、式が入力型への定数式変換を持たない定数パターンの場合、縮小された型は定数の型になります。
  • それ以外の場合、Pが、定数式が入力型への定数式変換を持たないリレーショナル パターンの場合、縮小された型は定数の型になります。
  • それ以外の場合、 Por パターンの場合、 このような共通型 が存在する場合、 縮小された型 はサブパターンの縮小型の共通型になります。 このため、共通型アルゴリズムでは、ID、ボックス化、および暗黙的な参照変換のみが考慮され、 or パターンのシーケンスのすべてのサブパターンが考慮されます (かっこで保護されたパターンは無視されます)。
  • それ以外の場合、 Pand パターンの場合、 縮小された型 は右のパターンの 狭い型 になります。 また、左パターンの 狭いタイプ は、右パターンの 入力タイプ である。
  • それ以外の場合、Pの縮小された型Pの入力型です。

: 文法で示されているように、 notandよりも優先され、 orよりも優先されます。 これは、かっこを使用して明示的に指定またはオーバーライドできます。 注釈

パターンisの右側に表示される場合、パターンの範囲は文法によって決まります。その結果、パターン演算子andor、およびパターン内のnotは、パターンの外側の論理演算子&&||、および!よりも厳密にバインドされます。

例:

Console.WriteLine(Classify(13));
Console.WriteLine(Classify(-100));
Console.WriteLine(Classify(5.7));

static string Classify(double measurement) => measurement switch
{
    < -40.0 => "Too low",
    >= -40.0 and < 0 => "Low",
    >= 0 and < 10.0 => "Acceptable",
    >= 10.0 and < 20.0 => "High",
    >= 20.0 => "Too high",
    double.NaN => "Unknown",
};

生成される出力は次のとおりです。

High
Too low
Acceptable

end の例

例:

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));

static string GetCalendarSeason(DateTime date) => date.Month switch
{
    3 or 4 or 5 => "spring",
    6 or 7 or 8 => "summer",
    9 or 10 or 11 => "autumn",
    12 or 1 or 2 => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date),
      $"Date with unexpected month: {date.Month}."),
};

生成される出力は次のとおりです。

winter
autumn
spring

end の例

例:

object msg = "msg";
object obj = 5;
bool flag = true;

// This is parsed as: (msg is (not int) or string)
result = msg is not int or string;
Console.WriteLine($"msg (\"msg\"): msg is not int or string: {result}");

// This is parsed as: (obj is (int or string)) && flag
bool result = obj is int or string && flag;
Console.WriteLine($"obj (5), flag (true): obj is int or string && flag: {result}");

// This is parsed as: (obj is int) || ((obj is string) && flag)
result = obj is int || obj is string && flag;
Console.WriteLine($"obj (5), flag (true): obj is int || obj is string && flag: {result}");

flag = false;
// This is parsed as: (obj is (int or string)) && flag
result = obj is int or string && flag;
Console.WriteLine($"obj (5), flag (false): obj is int or string && flag: {result}");

// This is parsed as: (obj is int) || ((obj is string) && flag)
result = obj is int || obj is string && flag;
Console.WriteLine($"obj (5), flag (false): obj is int || obj is string && flag: {result}");

生成される出力は次のとおりです。

msg ("msg"): msg is not int or string: True
obj (5), flag (true): obj is int or string && flag: True
obj (5), flag (true): obj is int || obj is string && flag: True
obj (5), flag (false): obj is int or string && flag: False
obj (5), flag (false): obj is int || obj is string && flag: True

end の例

11.3 パターンのサブ再開

switch ステートメントでは、前の一連の非ガード ケース (§13.8.3) によって、ケースのパターンがsubsumed場合はエラーになります。 非公式には、これは、入力値が前のいずれかのケースで一致したことを意味します。 次の規則は、一連のパターンが特定のパターンをサブスムするタイミングを定義します。

パターンP次のいずれかの条件が保持されている場合、定数K一致します。

  • そのパターンのランタイム動作の仕様は、 PKと一致することです。
  • Pは型Tのtype_patternであり、Knullされず、Kのランタイム型がTか、Tから派生した型、またはTを実装する型です。
  • Pは演算子 «op» と定数vを持つrelational_patternであり、式K «op» vtrueに評価されます。
  • Pnegated_patternでありnot P₁P₁Kと一致しません。
  • Pconjunctive_patternでありP₁ and P₂P₁は両方ともKと一致し、P₂Kと一致します。
  • Pdisjunctive_patternでありP₁ or P₂P₁Kと一致するか、P₂Kに一致します。
  • Pdiscard_patternです。

一連のパターン Qsubsumes 次のいずれかの条件が満たされている場合に P パターンです。

  • Pは定数パターンであり、セットQのパターンのいずれかがPの変換後の値と一致します
  • Pは var パターンであり、パターン入力値の型 (Q) に対してパターンのセットが exhaustive (§11.4) であり、パターン入力値が null 許容型でないか、Qのパターンがnullに一致します。
  • Pは型Tを持つ宣言パターンであり、型Q (§11.4) に対してTパターンのセットがです。
  • Pは型Tのtype_patternであり、Qパターンのセットは型T網羅しています。
  • Pは演算子 «op» と定数値vを持つrelational_patternであり、リレーションシップ «op» vを満たす入力型のすべての値に対して、セットQのパターンがその値と一致します。
  • Pdisjunctive_patternでありP₁ or P₂サブスメP₁QサブスメP₂Qパターンのセットです。
  • Pconjunctive_patternでありP₁ and P₂少なくとも 1 つの保持: Qサブスメ P₁、またはサブスメP₂Q
  • Pnegated_patternでありnot P₁Qは、P₁で一致しない値のみを考慮して入力の種類を網羅しています。
  • Pdiscard_pattern であり、パターン入力値の型 Q パターンのセットは 完全 であり、パターン入力値が null 許容型ではないか、 Q のパターンが nullと一致します。
  • Qの一部のパターンはdisjunctive_patternでありQ₁ or Q₂そのパターンをQQ₁に置き換えると、サブスメPセットが生成されるか、Q₂に置き換えると、サブスメPセットが生成されます。
  • Qの一部のパターンはnegated_patternでありnot Q₁Pは一致する値Q₁一致しません。

11.4 パターンの網羅性

非公式には、null 以外の型のすべての可能な値に対して、セット内のパターンが適用される場合、パターンのセットは完全です。 次の規則は、一連のパターンが型に対していつ 完全 するかを定義します。

次のいずれかの条件が満たされている場合、型Q完全です。

  1. T は整数型または列挙型、またはいずれかの null 許容バージョンであり、 Tの null 非許容基になる型のすべての可能な値に対して、 Q のパターンはその値と一致します。
  2. Qの一部のパターンは、var パターン; または
  3. Qの一部のパターンは型D宣言パターンであり、ID 変換、暗黙的な参照変換、または T から D へのボックス化変換があります。
  4. Qの一部のパターンは型Dtype_patternであり、ID 変換、暗黙的な参照変換、またはTからDへのボックス化変換があります。
  5. Qの一部のパターンはdiscard_patternです。
  6. Qのパターンには、relational_patternconstant_patternの組み合わせが含まれており、その範囲は、Tの null 非許容の基になる型のすべての可能な値をまとめてカバーします。 float型とdouble型の場合、NaNはどのリレーショナル パターンにも一致しないため、それぞれSystem.Double.NaNまたはSystem.Single.NaNが含まれます。
  7. Qの一部のパターンはdisjunctive_patternP₁ or P₂であり、そのパターンをP₁P₂の両方に置き換えると、QT完全なセットが生成されます。
  8. Qの一部のパターンはnegated_patternnot P₁であり、Q内のパターンと、P₁が一致しない値は、Tのすべての可能な値をカバーします。 negated_patternnot P₁は、P₁Tの可能な値と一致しない場合、それ自体が網羅的です。
  9. Qの一部のパターンはconjunctive_patternP₁ and P₂であり、P₁のみを含むセットはT網羅しており、P₂のみを含むセットはT対して網羅的です。

: 型パターンに null 許容型が含まれている場合、そのパターンは型に対して完全である可能性がありますが、型パターンが null 値と一致しないため、警告が生成される可能性があります。 注釈

: 浮動小数点型の場合、どちらのリレーショナル パターンもNaNに一致しないため、パターン < 0>= 0の組み合わせは完全ではありません。 完全な正しいセットは、 < 0>= 0double.NaN (または float.NaN) です。 注釈

例:

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 の例