Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
11.1 Umum
Pola adalah bentuk sindikat yang dapat digunakan dengan is operator (§12.14.12), dalam switch_statement (§13.8.3), dan dalam switch_expression (§12.11) 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
: declaration_pattern
| constant_pattern
| var_pattern
| positional_pattern
| property_pattern
| discard_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
vadalahTextReader. Variabel jenisTextReadertidak pernah dapat memiliki nilai yang kompatibel dengan referensi denganstring: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
vadalahobject. Variabel jenisobjectdapat memiliki nilai yang kompatibel dengan referensi denganstring: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 is-type (§12.14.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 Tis-type dan polae is T _deklarasi setara jikaTbukan 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 T jika ada konversi identitas, konversi referensi implisit atau eksplisit, konversi tinju, atau konversi pembuka kotak 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 kotakT) cocok dengan polaT2 idjenis jika nilainya non-null danT2adalahT, atau beberapa jenis dasar atau antarmukaT. Misalnya, dalam fragmen kodeint? x = 3; if (x is int v) { /* code using v */ }Kondisi
ifpernyataan adalahtruepada runtime dan variabelvmemegang nilai3jenisintdi dalam blok. Setelah blok variabelvberada 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 ekspresie == vadalahtrue; sebaliknya - pola
Pcocok dengan nilai e jika mengembalikanobject.Equals(e, v).true
Contoh: Pernyataan
switchdalam 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 penetapan formulir(var, ...
) 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
| identifier ':' pattern
;
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
Deconstructada 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 danDeconstructdipanggil 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 dariDeconstruct. - Jika tidak, jika jenis dihilangkan, dan nilai input berjenis
objectatau beberapa jenis yang dapat dikonversi keSystem.ITupleoleh konversi referensi implisitSystem.ITuple, dan tidak ada pengidentifikasi 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 60contoh 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 pengidentifikasi.
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
snon-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 dengan jenis
{polaproperty_pattern_list}, 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 pengidentifikasi yang muncul di sisi kiri property_pattern_list harus 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.
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 abccontoh 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_expressionpolarelational_expressionis 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.0Di sini, pola buang digunakan untuk menangani
nulldan nilai bilangan bulat apa pun yang tidak memiliki anggota enumerasi yangDayOfWeeksesuai. Itu menjamin bahwaswitchekspresi menangani semua kemungkinan nilai input. 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 spesifikasi untuk perilaku runtime pola tersebut cocok dengan PK.
Sekumpulan pola mensubsumsi Qpola P jika salah satu kondisi berikut menahan:
-
Padalah pola konstanta dan salah satu pola dalam setQakan cocokPdengan nilai yang dikonversi -
Padalah pola var dan kumpulan pola lengkapQ -
Padalah pola deklarasi dengan jenisTdan kumpulan polaQlengkap untuk jenisT(§11.4).
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:
-
Tadalah jenis integral atau enum, atau versi nullable dari salah satunya, dan untuk setiap nilai yang mungkin dariTjenis yang mendasar yang tidak dapat diubah ke null, beberapa pola akanQcocok dengan nilai tersebut; atau - Beberapa pola dalam
Qadalah pola var; atau - Beberapa pola dalam
Qadalah pola deklarasi untuk jenisD, dan ada konversi identitas, konversi referensi implisit, atau konversi tinju dariTkeD.
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
ECMA C# draft specification