11 Pola dan pencocokan pola

11.1 Umum

Pola adalah bentuk sindikasi yang dapat digunakan dengan is operator (§12.15.12), dalam switch_statement (§13.8.3), dan dalam switch_expression (§12.12) untuk mengekspresikan bentuk data yang data masuknya akan dibandingkan. Pola mungkin rekursif, sehingga bagian data dapat dicocokkan dengan sub-pola.

Pola diuji terhadap nilai dalam sejumlah konteks:

  • Dalam pernyataan switch, pola label kasus diuji terhadap ekspresi pernyataan switch.
  • Dalam operator is-pattern , pola di sisi kanan diuji terhadap ekspresi di sebelah kiri.
  • Dalam ekspresi pengalihan, polaswitch_expression_arm diuji terhadap ekspresi di sisi kiri ekspresi switch.
  • Dalam konteks berlapis, sub-pola diuji terhadap nilai yang diambil dari properti, bidang, atau diindeks dari nilai input lainnya, tergantung pada formulir pola.

Nilai di mana pola diuji disebut nilai input pola.

11.2 Formulir pola

11.2.1 Umum

Pola mungkin memiliki salah satu formulir berikut:

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

Produksi '(' pattern ')' memungkinkan pola diapit dalam tanda kurung untuk menegakkan urutan evaluasi di antara pola yang dikombinasikan menggunakan salah satu logical_pattern.

Beberapa poladapat menghasilkan deklarasi variabel lokal.

Setiap formulir pola mendefinisikan kumpulan jenis untuk nilai input tempat pola dapat diterapkan. Pola Pberlaku untuk jenis T jika T berada di antara jenis yang nilainya mungkin cocok dengan pola. Ini adalah kesalahan waktu kompilasi jika pola P muncul dalam program untuk mencocokkan nilai input pola (§11.1) jenis T jika P tidak berlaku untuk T.

Contoh: Contoh berikut menghasilkan kesalahan waktu kompilasi karena jenis waktu kompilasi v adalah TextReader. Variabel jenis TextReader tidak pernah dapat memiliki nilai yang kompatibel dengan referensi dengan 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
}

Namun, berikut ini tidak menghasilkan kesalahan waktu kompilasi karena jenis waktu kompilasi v adalah object. Variabel jenis object dapat memiliki nilai yang kompatibel dengan referensi dengan string:

object v = Console.In;
if (v is string s)
{
    // code assuming v is a string
}

contoh akhir

Setiap formulir pola mendefinisikan kumpulan nilai yang polanya cocok dengan nilai saat runtime.

Urutan evaluasi operasi dan efek samping selama pencocokan pola (panggilan ke Deconstruct, akses properti, dan pemanggilan metode dalam System.ITuple) tidak ditentukan.

11.2.2 Pola deklarasi

declaration_pattern digunakan untuk menguji bahwa nilai memiliki jenis tertentu dan, jika pengujian berhasil, untuk secara opsional memberikan nilai dalam variabel jenis tersebut.

declaration_pattern
    : type simple_designation
    ;
simple_designation
    : discard_designation
    | single_variable_designation
    ;
discard_designation
    : '_'
    ;
single_variable_designation
    : identifier
    ;

Simple_designation dengan token _ akan dianggap sebagai discard_designation daripada single_variable_designation.

Jenis runtime nilai diuji terhadap jenis dalam pola menggunakan aturan yang sama yang ditentukan dalam operator tipe is (§12.15.12.1). Jika pengujian berhasil, pola cocok dengan nilai tersebut. Ini adalah kesalahan kompilasi-waktu jika jenis adalah jenis nilai nullable (§8.3.12) atau jenis referensi nullable (§8.9.3). Bentuk pola ini tidak pernah cocok dengan null nilai.

Catatan: Ekspresi e is T is-type dan pola e is T _ deklarasi setara ketika T bukan jenis nullable. catatan akhir

Mengingat nilai input pola (§11,1) e, jika simple_designationdiscard_designation, itu menunjukkan pembuangan (§9.2.9.2), dan nilai e tidak terikat pada apa pun. (Meskipun variabel yang dideklarasikan dengan nama _ mungkin berada dalam cakupan pada saat itu, variabel bernama tersebut tidak terlihat dalam konteks ini.) Jika tidak, jika simple_designationsingle_variable_designation, variabel lokal (§9.2.9) dari jenis yang diberikan yang dinamai oleh pengidentifikasi yang diberikan diperkenalkan. Variabel lokal tersebut diberi nilai nilai input pola saat pola cocok dengan nilai.

Kombinasi tertentu dari jenis statis nilai input pola dan jenis yang diberikan dianggap tidak kompatibel dan mengakibatkan kesalahan waktu kompilasi. Nilai jenis E statis dikatakan kompatibel dengan pola dengan jenis T jika ada konversi identitas, konversi referensi implisit atau eksplisit, konversi tinju, konversi pembuka kotak, atau konversi jenis nilai nullable implisit atau eksplisit dari E ke T, atau jika salah satu E atau T merupakan jenis terbuka (§8.4.3). Pola deklarasi penamaan jenis Tberlaku untuk setiap jenis E yang E kompatibel dengan pola .T

Catatan: Dukungan untuk jenis terbuka dapat paling berguna saat memeriksa jenis yang mungkin berupa jenis struct atau kelas, dan tinju harus dihindari. catatan akhir

Contoh: Pola deklarasi berguna untuk melakukan pengujian jenis run-time dari jenis referensi, dan menggantikan idiom

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

dengan sedikit lebih ringkas

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

contoh akhir

Contoh: Pola deklarasi dapat digunakan untuk menguji nilai jenis null: nilai jenis Nullable<T> (atau kotak T) cocok dengan pola T2 id jenis jika nilainya non-null dan T2 adalah T, atau beberapa jenis dasar atau antarmuka T. Misalnya, dalam fragmen kode

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

Kondisi if pernyataan adalah true pada runtime dan variabel v memegang nilai 3 jenis int di dalam blok. Setelah blok variabel v berada dalam cakupan, tetapi tidak pasti ditetapkan. contoh akhir

11.2.3 Pola konstanta

constant_pattern digunakan untuk menguji nilai nilai input pola (§11,1) terhadap nilai konstanta yang diberikan.

constant_pattern
    : constant_expression
    ;

Pola Pkonstanta berlaku untuk jenis T jika ada konversi implisit dari ekspresi P konstanta ke jenis T.

Untuk pola Pkonstanta , nilai yang dikonversi adalah

  • jika jenis nilai input pola adalah jenis integral atau jenis enum, nilai konstanta pola dikonversi ke jenis tersebut; Sebaliknya
  • jika jenis nilai input pola adalah versi nullable dari jenis integral atau jenis enum, nilai konstan pola dikonversi ke jenis yang mendasarnya; Sebaliknya
  • nilai nilai konstanta pola.

Mengingat nilai input pola e dan pola P konstanta dengan nilai yang dikonversi v,

  • jika e memiliki jenis integral atau jenis enum, atau bentuk nullable dari salah satunya, dan v memiliki jenis integral, pola Pcocok dengan nilai e jika hasil ekspresi e == v adalah true; sebaliknya
  • pola P cocok dengan nilai e jika mengembalikan object.Equals(e, v).true

Contoh: Pernyataan switch dalam metode berikut menggunakan lima pola konstanta dalam label kasusnya.

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

contoh akhir

Pola 11.2.4 Var

Var_patterncocok dengan setiap nilai. Artinya, operasi pencocokan pola dengan var_pattern selalu berhasil.

Var_patternberlaku untuk setiap jenis.

var_pattern
    : 'var' designation
    ;
designation
    : simple_designation
    | tuple_designation
    ;
tuple_designation
    : '(' designations? ')'
    ;
designations
    : designation (',' designation)*
    ;

Mengingat nilai input pola (§11,1) e, jika penandaandiscard_designation, itu menunjukkan pembuangan (§9.2.9.2), dan nilai e tidak terikat ke apa pun. (Meskipun variabel yang dideklarasikan dengan nama tersebut mungkin berada dalam cakupan pada saat itu, variabel bernama tersebut tidak terlihat dalam konteks ini.) Jika tidak, jika penunjukansingle_variable_designation, pada runtime nilai e terikat ke variabel lokal yang baru diperkenalkan (§9,2,9) dari nama tersebut yang jenisnya adalah jenis statis e, dan nilai input pola ditetapkan ke variabel lokal tersebut.

Ini adalah kesalahan jika nama var akan mengikat ke jenis tempat var_pattern digunakan.

Jika penandaan adalah tuple_designation, polanya setara dengan positional_pattern (§11,2,5) dari (var formulir, ... ) di mana penetapanadalah yang ditemukan dalam tuple_designation. Misalnya, polanya var (x, (y, z)) setara dengan (var x, (var y, var z)).

11.2.5 Pola posisi

positional_pattern memeriksa bahwa nilai input bukan null, memanggil metode yang sesuai Deconstruct (§12,7), dan melakukan pencocokan pola lebih lanjut pada nilai yang dihasilkan. Ini juga mendukung sintaks pola seperti tuple (tanpa jenis yang disediakan) ketika jenis nilai input sama dengan jenis yang berisi Deconstruct, atau jika jenis nilai input adalah jenis tuple, atau jika jenis nilai input adalah atau jika jenis nilai input adalah object atau System.ITuple dan jenis runtime ekspresi mengimplementasikan System.ITuple.

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

Mengingat kecocokan nilai input dengansubpattern(jenis) pola, metode dipilih dengan mencari dalam jenis untuk deklarasi Deconstruct yang dapat diakses dan memilih satu di antaranya menggunakan aturan yang sama seperti untuk deklarasi dekonstruksi. Ini adalah kesalahan jika positional_pattern menghilangkan jenis, memiliki satu subpattern tanpa pengidentifikasi, tidak memiliki property_subpattern dan tidak memiliki simple_designation. Ini membedakan antara constant_pattern yang dikurung dan positional_pattern. Untuk mengekstrak nilai yang cocok dengan pola dalam daftar,

  • Jika jenis dihilangkan dan jenis ekspresi input adalah jenis tuple, maka jumlah subpattern harus sama dengan kardinalitas tuple. Setiap elemen tuple dicocokkan dengan subpattern yang sesuai, dan kecocokan berhasil jika semua ini berhasil. Jika ada subpattern yang memiliki pengidentifikasi, maka itu akan memberi nama elemen tuple pada posisi yang sesuai dalam jenis tuple.
  • Jika tidak, jika cocok Deconstruct ada sebagai anggota jenis, itu adalah kesalahan waktu kompilasi jika jenis nilai input tidak kompatibel dengan pola dengan jenis. Pada runtime, nilai input diuji terhadap jenis. Jika ini gagal, maka kecocokan pola posisi gagal. Jika berhasil, nilai input dikonversi ke jenis ini dan Deconstruct dipanggil dengan variabel segar yang dihasilkan kompilator untuk menerima parameter output. Setiap nilai yang diterima dicocokkan dengan subpattern yang sesuai, dan kecocokan berhasil jika semua ini berhasil. Jika ada subpattern yang memiliki pengidentifikasi, maka itu akan memberi nama parameter pada posisi yang sesuai dari Deconstruct.
  • Jika tidak, jika jenis dihilangkan, dan nilai input berjenis object atau beberapa jenis yang dapat dikonversi ke System.ITuple oleh konversi referensi implisit, dan tidak ada System.ITuple yang muncul di antara subpattern, maka kecocokan menggunakan .
  • Jika tidak, polanya adalah kesalahan waktu kompilasi.

Urutan di mana subpattern dicocokkan pada runtime tidak ditentukan, dan kecocokan yang gagal mungkin tidak mencoba mencocokkan semua subpattern.

Contoh: Di sini, kami mendekonstruksi hasil ekspresi dan mencocokkan nilai yang dihasilkan dengan pola berlapis yang sesuai:

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

contoh akhir

Contoh: Nama elemen tuple dan parameter Dekonstruksi dapat digunakan dalam pola posisional, sebagai berikut:

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

Output yang dihasilkan adalah

Sum of [10 20 30] is 60

contoh akhir

11.2.6 Pola properti

property_pattern memeriksa bahwa nilai input bukan null, dan secara rekursif cocok dengan nilai yang diekstrak oleh penggunaan properti atau bidang yang dapat diakses.

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

Ini adalah kesalahan jika subpatterndari property_pattern tidak berisi subpattern_name.

Ini adalah kesalahan kompilasi-waktu jika jenis adalah jenis nilai nullable (§8.3.12) atau jenis referensi nullable (§8.9.3).

Catatan: Pola pemeriksaan null keluar dari pola properti sepele. Untuk memeriksa apakah string s non-null, seseorang dapat menulis salah satu formulir berikut:

#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 {}) ...

catatan akhir

Mengingat kecocokan ekspresi e dengansubpattern{jenis} pola, itu adalah kesalahan waktu kompilasi jika ekspresi e tidak kompatibel dengan jenis T yang ditunjuk berdasarkan jenis. Jika jenis tidak ada, jenis diasumsikan sebagai jenis statis e. Setiap subpattern_name yang muncul di sisi kiri subpattern-nya akan menunjuk properti atau bidang T yang dapat dibaca yang dapat diakses. Jika simple_designationproperty_pattern ada, itu mendeklarasikan variabel pola jenis T.

Pada runtime, ekspresi diuji terhadap T. Jika ini gagal, maka kecocokan pola properti gagal, dan hasilnya adalah false. Jika berhasil, maka setiap bidang atau properti property_subpattern dibaca, dan nilainya cocok dengan pola yang sesuai. Hasil dari seluruh kecocokan false hanya jika hasil dari salah satu dari ini adalah false. Urutan di mana subpattern dicocokkan tidak ditentukan, dan kecocokan yang gagal mungkin tidak menguji semua subpattern saat runtime. Jika kecocokan berhasil dan simple_designationproperty_pattern adalah single_variable_designation, variabel yang dideklarasikan diberi nilai yang cocok.

property_pattern dapat digunakan untuk pencocokan pola dengan jenis anonim.

Subpattern_name dapat mereferensikan anggota berlapis. Dalam kasus seperti itu, penerima untuk setiap pencarian nama adalah jenis anggota sebelumnya T₀, mulai dari jenis inputproperty_pattern. Jika T adalah jenis nullable, T₀ adalah jenis yang mendasarnya, jika tidak , T₀ sama dengan T. Misalnya, pola formulir { Prop1.Prop2: pattern } sama persis dengan { Prop1: { Prop2: pattern } }.

Catatan: Ini akan menyertakan pemeriksaan null ketika T adalah jenis nilai nullable atau jenis referensi. Pemeriksaan null ini berarti bahwa properti berlapis yang tersedia akan menjadi properti T₀, bukan dari T. Karena jalur anggota berulang diizinkan, kompilasi pencocokan pola dapat memanfaatkan bagian pola umum. catatan akhir

Contoh:

var o = ...;
if (o is string { Length: 5 } s) ...

contoh akhir

Contoh: Pemeriksaan jenis run-time dan deklarasi variabel dapat ditambahkan ke pola properti, sebagai berikut:

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."),
};

Output yang dihasilkan adalah

Hello
Hi!
12345
abc

contoh akhir

11.2.7 Buang pola

Setiap ekspresi cocok dengan pola buang, yang menghasilkan nilai ekspresi yang dibuang.

discard_pattern
    : '_'
    ;

Ini adalah kesalahan waktu kompilasi untuk menggunakan pola buang dalam relational_expressionpolais bentuk atau sebagai pola switch_label.

Catatan: Dalam kasus tersebut, untuk mencocokkan ekspresi apa pun, gunakan var_pattern dengan buang var _. catatan akhir

Contoh:

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

Output yang dihasilkan adalah

5.0
0.0
0.0

Di sini, pola buang digunakan untuk menangani null dan nilai bilangan bulat apa pun yang tidak memiliki anggota enumerasi yang DayOfWeek sesuai. Itu menjamin bahwa switch ekspresi menangani semua kemungkinan nilai input. contoh akhir

11.2.8 Pola jenis

type_pattern digunakan untuk menguji bahwa nilai input pola (§11,1) memiliki jenis tertentu.

type_pattern
    : type
    ;

Pola jenis penamaan jenis Tberlaku untuk setiap jenis E yang Ekompatibel dengan T pola (§11.2.2).

Jenis runtime nilai diuji terhadap jenis menggunakan aturan yang sama yang ditentukan dalam operator tipe is (§12.15.12.1). Jika pengujian berhasil, pola cocok dengan nilai tersebut. Ini adalah kesalahan waktu kompilasi jika jenisnya adalah jenis yang dapat diubah ke null. Bentuk pola ini tidak pernah cocok dengan null nilai.

11.2.9 Pola relasional

relational_pattern digunakan untuk menguji nilai input pola secara relasional (§11,1) terhadap nilai konstanta.

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

relational_expression dalam relational_pattern diperlukan untuk mengevaluasi ke nilai konstanta.

Pola relasional mendukung operator <relasional , , <=>, dan >= pada semua jenis bawaan yang mendukung operator relasional biner tersebut dengan kedua operan memiliki jenis yang sama: sbyte, , , byteshort, ushortintuintlongulongcharfloatdoubledecimal, nint, nuint, , dan enum.

relational_patternberlaku untuk jenis T jika operator relasional biner bawaan yang sesuai didefinisikan dengan kedua operan jenis T, atau jika konversi nullable atau unboxing eksplisit ada dari T ke jenis ekspresi konstanta.

Ini adalah kesalahan waktu kompilasi jika ekspresi mengevaluasi ke double.NaN, float.NaN, atau konstanta null.

Ketika nilai input memiliki jenis yang didefinisikan oleh operator relasional biner bawaan yang sesuai, evaluasi operator tersebut diambil sebagai arti pola relasional. Jika tidak, nilai input dikonversi ke jenis ekspresi konstanta menggunakan konversi nullable atau unboxing eksplisit. Ini adalah kesalahan waktu kompilasi jika tidak ada konversi tersebut. Pola dianggap tidak cocok jika konversi gagal. Jika konversi berhasil, hasil operasi pencocokan pola adalah hasil mengevaluasi ekspresi e «op» v di mana e adalah input yang dikonversi, «op» adalah operator relasional, dan v merupakan ekspresi konstanta.

Contoh:

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",
};

Output yang dihasilkan adalah

Too high
Unknown
Acceptable

contoh akhir

11.2.10 Pola logis

logical_pattern digunakan untuk meniadakan hasil kecocokan pola, atau untuk menggabungkan hasil dari beberapa kecocokan pola menggunakan sambungan (and) atau disjunksi (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
    ;

not, and, dan or secara kolektif disebut operator pola.

Negated_pattern cocok jika pola yang ditiadakan tidak cocok, dan sebaliknya. conjunctive_pattern mengharuskan kedua pola untuk dicocokkan. Disjunctive_pattern memerlukan salah satu pola untuk dicocokkan. Tidak seperti rekan operator bahasa mereka, && dan ||, and dan orbukan operator sirkuit pendek.

Ini adalah kesalahan waktu kompilasi agar variabel pola dideklarasikan di bawah not operator pola atau or .

Catatan: Karena tidak juga tidak notor dapat menghasilkan penugasan pasti untuk variabel pola, kesalahan untuk mendeklarasikannya dalam posisi tersebut. catatan akhir

Dalam conjunctive_pattern, jenis input pola kedua dipersempit oleh persyaratan penyempitan jenis pola pertama .and Jenis pola yang P didefinisikan sebagai berikut:

  • Jika P adalah pola jenis, jenis yang dipersempit adalah jenis jenis pola jenis.
  • Jika tidak, jika P adalah pola deklarasi, jenis yang dipersempit adalah jenis pola deklarasi.
  • Jika tidak, jika P adalah pola rekursif yang memberikan jenis eksplisit, jenis yang dipersempit adalah jenis tersebut.
  • Jika tidak, jika P dicocokkan melalui aturan untuk ITuple dalam positional_pattern (§11.2.5), jenis yang dipersempit adalah jenis System.ITuple.
  • Jika tidak, jika P adalah pola konstanta di mana konstanta bukan konstanta null dan di mana ekspresi tidak memiliki konversi ekspresi konstanta ke jenis input, jenis yang dipersempit adalah jenis konstanta.
  • Jika tidak, jika P adalah pola relasional di mana ekspresi konstanta tidak memiliki konversi ekspresi konstan ke jenis input, jenis yang dipersempit adalah jenis konstanta.
  • Jika tidak, jika P adalah or pola, jenis yang dipersempit adalah jenis umum dari jenis subpattern yang dipersempit jika jenis umum seperti itu ada. Untuk tujuan ini, algoritma jenis umum hanya mempertimbangkan konversi identitas, tinju, dan referensi implisit, dan mempertimbangkan semua subpattern or dari urutan pola (mengabaikan pola yang dikurung).
  • Jika tidak, jika P adalah and pola, jenis yang dipersempit adalah jenis pola yang tepat yang dipersempit . Selain itu, jenis pola kiri yang dipersempit adalah jenis input pola kanan.
  • Jika tidak , jenisP yang dipersempit adalah Pjenis input.

Catatan: Seperti yang ditunjukkan oleh tata bahasa, not lebih diutamakan daripada and, yang lebih diutamakan daripada or. Ini dapat secara eksplisit ditunjukkan atau ditimpa dengan menggunakan tanda kurung. catatan akhir

Ketika pola muncul di sisi iskanan , tingkat pola ditentukan oleh tata bahasa; sebagai hasilnya, operator andpola , , ordan not dalam pola mengikat lebih ketat daripada operator &&logis , , ||dan ! di luar pola.

Contoh:

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",
};

Output yang dihasilkan adalah

High
Too low
Acceptable

contoh akhir

Contoh:

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}."),
};

Output yang dihasilkan adalah

winter
autumn
spring

contoh akhir

Contoh:

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

Output yang dihasilkan adalah

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

contoh akhir

11.3 Subsumpsi pola

Dalam pernyataan pengalihan, itu adalah kesalahan jika pola kasus disubsumsikan oleh kumpulan kasus yang tidak dijaga sebelumnya (§13.8.3). Secara informal, ini berarti bahwa nilai input apa pun akan dicocokkan oleh salah satu kasus sebelumnya. Aturan berikut menentukan kapan sekumpulan pola mensubsumsi pola tertentu:

Pola Pakan cocok dengan konstanta K jika salah satu kondisi berikut menahan:

  • spesifikasi untuk perilaku runtime pola tersebut adalah yang P cocok Kdengan .
  • P adalah type_pattern untuk jenis T dan K bukan null dan jenis K runtime adalah T atau jenis yang berasal dari T atau jenis yang mengimplementasikan T.
  • P adalah relational_pattern dengan operator «op» dan konstanta v, dan ekspresi K «op» v akan mengevaluasi ke true.
  • P adalah negated_patternnot P₁ dan P₁ tidak akan cocok K.
  • P adalah conjunctive_patternP₁ and P₂ dan keduanya P₁ akan cocok K dan P₂ akan cocok K.
  • P adalah disjunctive_patternP₁ or P₂ dan akan P₁ cocok K atau P₂ akan cocok K.
  • P adalah discard_pattern.

Sekumpulan pola mensubsumsi Qpola P jika salah satu kondisi berikut menahan:

  • P adalah pola konstanta dan salah satu pola dalam set Q akan cocok Pdengan nilai yang dikonversi
  • Padalah pola var dan kumpulan pola lengkap Q
  • Padalah pola deklarasi dengan jenis T dan kumpulan pola Q lengkap untuk jenis T (§11.4).
  • P adalah type_pattern untuk jenis T dan kumpulan pola Qlengkap untuk jenis T.
  • P adalah relational_pattern dengan operator «op» dan nilai vkonstanta , dan untuk setiap nilai jenis input yang memenuhi relasi «op» v, beberapa pola dalam set Q akan cocok dengan nilai tersebut.
  • P adalah disjunctive_patternP₁ or P₂ dan set subjudul QP₁ dan Q subjudul P₂pola .
  • P adalah conjunctive_patternP₁ and P₂ dan setidaknya salah satu penangguhan berikut: Q subjudul P₁, atau Q subjudul P₂.
  • P adalah negated_patternnot P₁ dan Qlengkap untuk jenis input yang hanya mempertimbangkan nilai yang tidak cocok dengan P₁.
  • P adalah discard_pattern dan kumpulan pola Qlengkap untuk jenis nilai input pola, dan nilai input pola bukan dari jenis nullable atau beberapa pola di Q akan cocok nulldengan .
  • Beberapa pola dalam Q adalah disjunctive_patternQ₁ or Q₂ dan mengganti pola tersebut dengan Q₁ in Q akan menghasilkan set yang subsumes P, atau menggantinya dengan Q₂ akan menghasilkan set yang subsumes P.
  • Beberapa pola dalam Q adalah negated_patternnot Q₁ dan P tidak akan cocok dengan nilai apa pun yang Q₁ cocok.

11.4 Kelelahan pola

Secara informal, satu set pola lengkap untuk jenis jika, untuk setiap nilai yang mungkin dari jenis itu selain null, beberapa pola dalam set berlaku. Aturan berikut menentukan kapan sekumpulan pola lengkap untuk jenis:

Sekumpulan pola Q lengkap untuk jenis T jika salah satu kondisi berikut menahan:

  1. T adalah jenis integral atau enum, atau versi nullable dari salah satunya, dan untuk setiap nilai yang mungkin dari Tjenis yang mendasar yang tidak dapat diubah ke null, beberapa pola akan Q cocok dengan nilai tersebut; atau
  2. Beberapa pola dalam Q adalah pola var; atau
  3. Beberapa pola dalam Q adalah pola deklarasi untuk jenis D, dan ada konversi identitas, konversi referensi implisit, atau konversi tinju dari T ke D; atau
  4. Beberapa pola dalam Q adalah type_pattern untuk jenis D, dan ada konversi identitas, konversi referensi implisit, atau konversi tinju dari T ke D; atau
  5. Beberapa pola dalam Q adalah discard_pattern; atau
  6. Pola termasuk Q kombinasi relational_patterndan constant_patternyang rentangnya secara kolektif mencakup setiap nilai yang mungkin dari Tjenis yang mendasar yang tidak dapat diubah ke null. Untuk float jenis dan double , ini mencakup System.Double.NaN atau System.Single.NaN masing-masing, NaN karena tidak cocok dengan pola relasional apa pun; atau
  7. Beberapa pola dalam Q adalah disjunctive_patternP₁ or P₂, dan mengganti pola tersebut dengan keduanya P₁ dan P₂ dalam Q menghasilkan satu set yang lengkap untukT; atau
  8. Beberapa pola dalam Q adalah negated_patternnot P₁, dan pola bersama Q dengan nilai yang tidak cocok dengan P₁ mencakup setiap nilai yang mungkin dari T. negated_patternnot P₁ lengkap dengan sendirinya ketika P₁ tidak cocok dengan nilai Tyang mungkin ; atau
  9. Beberapa pola dalam Q adalah conjunctive_patternP₁ and P₂, dan set yang hanya P₁ berisi lengkap untukT dan set yang hanya P₂berisi lengkap untukT.

Catatan: Ketika pola jenis menyertakan jenis nullable, pola mungkin lengkap untuk jenis tetapi masih menghasilkan peringatan karena pola jenis tidak akan cocok dengan null nilai. catatan akhir

Catatan: Untuk jenis floating-point, kombinasi pola < 0 dan >= 0tidak lengkap karena pola relasional tidak cocok NaN. Set lengkap yang benar adalah < 0, , >= 0dan double.NaN (atau float.NaN). catatan akhir

Contoh:

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

contoh akhir