11 Desen ve desen eşleştirme

11.1 Genel

İşleç (is§12.15.12), switch_statement (§13.8.3) ve switch_expression (§12.12) ile birlikte gelen verilerin karşılaştırılacağı veri şeklini tanımlamak için kullanılabilir. Desenler, verilerin parçaları alt desenlerle eşleştirilirken iç içe yerleştirilmiş olabilir.

Desen, çeşitli bağlamlardaki bir değere göre test edilir:

  • bir switch_statement, switch_label deseniswitch_statementselector_expression karşı test edilir.
  • is-pattern işleciyle sağ taraftaki desen, soldaki ifadeye göre test edilir.
  • bir switch_expression, bir switch_expression_armdeseniswitch_expression sol tarafındaki ifadeye göre test edilir.
  • İç içe bağlamlarda alt desen, desen formuna bağlı olarak özelliklerden, alanlardan alınan veya diğer giriş değerlerinden dizine alınan değerlerle test edilir.

Bir desenin sınandığı değer, desen giriş değeri olarak adlandırılır.

P ile eşleşen P herhangi bir giriş değeri öğesi üyelerinden Qbiri tarafından eşleşiyorsa, desen korumasız desenler Q kümesi tarafından alt numaralandırılır.

Switch deyiminde (§13.8.3), bir servis talebinin deseni önceki korumasız (§13.8.3) servis talebi kümesi tarafından altnumaralandırılırsa bu bir hatadır. Bir switch ifadesinde (§12.12), bir switch_expression_arm deseninin önceki korumasızswitch_expression_armdesenleri kümesi tarafından alt düzeye çıkarılması hatadır.

Olası her giriş değeri için kümedeki bazı desenler geçerliyse, bir dizi desen kapsamlıdır. Bir uygulama, bir dizi desenin kapsamlı olmadığını algıladığında bir uyarı yayınlar.

11.2 Desen formları

11.2.1 Genel

Bir desen aşağıdaki formlardan birine sahip olabilir:

pattern
    : logical_pattern
    ;

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

parenthesized_pattern
    : '(' pattern ')'
    ;

Üretim, '(' pattern ')' logical_pattern birini kullanarak birleştirilen desenler arasında değerlendirme sırasını zorlamak için desenin paranteziçine alınmasına olanak tanır.

Giriş hem constant_pattern hem de positional_pattern olarak söz dizimsel olarak tanınabiliyorsa constant_pattern seçilmelidir.

Bazı desenleryerel bir değişkenin bildirimiyle sonuçlanabilir.

Her desen formu, desenin uygulanabileceği giriş değerleri için tür kümesini tanımlar. Desen, değerleri P eşleşebilecek türler arasındaysa, T bir tür için geçerlidirT Için geçerli değilse P , bir programda desen giriş değeriyle (§11.1) T eşleşecek şekilde görüntüleniyorsa P derleme zamanı hatasıdır T.

Örnek: Aşağıdaki örnek, derleme zamanı türü v olduğundan TextReaderderleme zamanı hatası oluşturur. Türündeki TextReader bir değişkenin hiçbir zaman ile stringbaşvuru uyumlu bir değeri olamaz:

TextReader v = Console.In; // compile-time type of 'v' is 'TextReader'
if (v is string) // compile-time error
{
    // code assuming v is a string
}

Ancak, aşağıdaki derleme zamanı türü v olduğundan objectderleme zamanı hatası oluşturmaz. Türünde object bir değişken, ile stringbaşvuru uyumlu bir değere sahip olabilir:

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

son örnek

Her desen formu, desenin çalışma zamanındaki değerle eşleşdiği değer kümesini tanımlar.

Desen eşleştirme sırasında işlemlerin ve yan etkilerin değerlendirilmesi sırası ( Deconstruct, özellik erişimleri ve üyelerinin System.Runtime.CompilerServices.ITupleçağrıları ) belirtilmez.

11.2.2 Bildirim düzeni

declaration_pattern, bir değerin belirli bir türe sahip olup olmadığını test etmek ve test başarılı olursa isteğe bağlı olarak bu türdeki bir değişkende değer sağlamak için kullanılır.

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

Bir simple_designation tanındığında hem discard_designation hem de single_variable_designation alternatifler geçerliyse, ilki seçilir.

Not: ANTLR, simple_designation alternatiflerinin sıralanması nedeniyle belirtilen seçimi otomatik olarak yapar. son not

Tür null atanabilir bir değer türü (§8.3.12) veya null atanabilir başvuru türü (§8.9.3) ise derleme zamanı hatasıdır.

Değerin çalışma zamanı türü, is-type işlecinde (§12.15.12.1) belirtilen kurallar kullanılarak desendeki türe göre test edilir. Test başarılı olursa, desen bu değerle eşleşir .

Not: her ikisi de geçerli olduğunda is-type ifadesi e is T ve bildirim deseni e is T _ eşdeğerdir. son not

Desen giriş değeri (§11.1) e verildiğinde, simple_designationbir discard_designation ise, atma (§9.2.9.2) değerini belirtirse , e değeri hiçbir şeye bağlı değildir. Aksi takdirde , simple_designationbir single_variable_designation ise, verilen tanımlayıcı tarafından adlandırılan türün yerel değişkeni (§9.2.9) kullanıma sunulur. Bu yerel değişkene, desen değerle eşleştiğinde desen giriş değerinin değeri atanır.

Not: _ içindeki bu işlem, desen olarak yazılmış tek başına _ bir sabitten (§11.2.7) farklıdır: İkinci durumda, kapsam içi sabit veya varsa adlı _tür gizli değildir. son not

E Kimlik dönüştürmesi, örtük veya açık başvuru dönüştürmesi, kutulama dönüştürmesi, kutulama dönüştürmesi veya 'den 'a örtük veya açık null atanabilir değer türü dönüştürmesi varsa ya da açık bir türse TE (T) türüyle T desen uyumlu olduğu söylenir. Bir türü adlandıran bildirim deseni, her tür T için (E) ile Euyumlu desen için T. Statik türü T ile uyumlu desen olmayan bir desen giriş değeriyle (E) eşleştirmek için bir T bildirim deseni adlandırması kullanılırsa, derleme zamanı hatasıdır.

Not: Açık türler için destek en çok yapı veya sınıf türleri olabilecek türleri denetlerken yararlı olabilir ve kutulamadan kaçınılmalıdır. son not

Örnek: Bildirim deseni, başvuru türlerinin çalışma zamanı türü testlerini gerçekleştirmek için kullanışlıdır ve deyiminin yerini alır

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

biraz daha kısa

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

son örnek

Örnek: Bildirim deseni, null atanabilir türlerin değerlerini test etmek için kullanılabilir: değer null olmayan ve Nullable<T>Tise tür deseni T2 id (veya kutuluT2) bir tür deseni T ile eşleşir ya da bazı temel türü veya arabirimi.T Örneğin, kod parçasında

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

deyiminin if koşulu çalışma zamanındadır true ve değişkenv, bloğun içindeki türün 3 değerini int tutar. Blok sonrasında değişken v kapsam içindedir, ancak kesinlikle atanmamış olur. son örnek

11.2.3 Sabit deseni

Bir desen giriş değerinin (§11.1) değerini verilen sabit değerle test etmek için bir constant_pattern kullanılır.

constant_pattern
    : constant_expression
    ;

sabit ifadesinden PtürüneTTörtük bir dönüştürme varsa veya veya ise ve sabit ifadesi türündeyse TSystem.Span<char>System.ReadOnlySpan<char> ve sabit ifadesi değişmez değer değilsenull, bir tür string için sabit desen PP geçerlidir.

Sabit bir desen içinP, dönüştürülen değeri

  • Desen giriş değerinin türü bir tamsayı türü veya bir numaralandırma türüyse, desenin sabit değeri bu türe dönüştürülür; yoksa
  • Desen giriş değerinin türü bir tamsayı türünün veya bir sabit sabit türünün null atanabilir sürümüyse, desenin sabit değeri temel alınan türüne dönüştürülür; yoksa
  • desenin sabit değerinin değeri.

Esahip sabit bir desen P verildiğinde,

  • e tamsayı türüne veya sabit listesi türüne veya bunlardan birinin null atanabilir bir biçimine ve v tamsayı türüne sahipse, ifadenin P sonucu ise desen ; aksi takdirde
  • e veya System.ReadOnlySpan<char>türündeyse System.Span<char> ve v sabit bir dizeyse ve v sabit değerine nullsahip değilse, desen P döndürürse System.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(v))edeğeriyle eşleşirtrue; aksi takdirde
  • deseni P.

Örnek: switch Aşağıdaki yöntemdeki deyimi, büyük/küçük harf etiketlerinde beş sabit desen kullanır.

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

son örnek

11.2.4 Var deseni

var_pattern her değerle eşleşir. Başka bir ifadeyle, var_pattern ile desen eşleştirme işlemi her zaman başarılı olur.

var_pattern her tür için geçerlidir.

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

Bir desen giriş değeri (§11.1) e verildiğinde, atamadiscard_designation ise atılan değeri (§9.2.9.2) belirtir ve e değeri hiçbir şeye bağlı değildir. (Bu ada sahip bildirilen bir değişken bu noktada kapsam içinde olsa da, bu adlandırılmış değişken bu bağlamda görülmez.) Aksi takdirde, atamasingle_variable_designation ise çalışma zamanında e değeri, türü statik e türü olan ve desen giriş değeri bu yerel değişkene atanmış olan bu adın yeni tanıtılan yerel değişkenine (§9.2.9) bağlıdır.

Advar, bir var_pattern kullanıldığı bir türe bağlanacaksa bu bir hatadır.

Atama bir tuple_designation ise, desen form gösteriminin(var (§11.2.5) eşdeğerdir, ... )burada, tuple_designation içinde bulunanlar olarak ifadeedilir. Örneğin, desen var (x, (y, z)) ile (var x, (var y, var z))eşdeğerdir.

11.2.5 Konumsal desen

positional_pattern, giriş değerinin değil olup olmadığını nulldenetler, bu değerden bir değer dizisi ayıklar ve ayıklanan her değeri ilgili alt formülle eşleştirir. Değerler üç yoldan biriyle ayıklanır: girişi bir tanımlama grubu olarak kabul ederek, bir Deconstruct yöntem çağırarak veya girişi aracılığıyla System.Runtime.CompilerServices.ITupledizine alarak.

Not: Burada kullanım Deconstruct , §12.7'de tanımlanan kaynak düzeyindeki yapıdan ayrıdır. son not

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

Ayraçlar arasında görünen alt parantezsayısı n olsun. Aşağıdaki durumlar sırayla uygulanarak derleme zamanında eşleşen strateji seçilir; koşulları karşılanan ilk durum kullanılır ve kalan durumlar dikkate alınmaz. Bir servis talebi seçildikten sonra bu strateji işlenir: bu durumda belirtilen derleme zamanı hataları bildirilir ve eşleştirme sonraki bir büyük/küçük harfe düşmez.

  1. Tanımlama grubu formu. Tür atlanırsa ve giriş değerinin statik türü bir tanımlama grubu türüyse (§8.3.11) veya giriş değeri bir tanımlama grubu değişmez değeriyse (§12.8.6) bu durum geçerlidir. n, bu tanımlama grubu türünün arity değerine eşit değilse, bu bir derleme zamanı hatasıdır. Çalışma zamanında, her tanımlama grubu öğesi karşılık gelen alt çizgiyle eşleştirilir; tüm bunlar başarılı olursa eşleşme başarılı olur. Herhangi bir alt belgenintanımlayıcısı varsa, bu tanımlayıcı tanımlama grubu öğesini tanımlama grubu türünde karşılık gelen konumda adlandıracaktır.
  2. Yapısızlaştırma formu. Aksi takdirde, türlerden biri varsa veya tür atlanırsa ve giriş değerinin statik türü erişilebilir Deconstruct bir yöntem (§12.7) içeriyorsa, bu durum geçerlidir. Tür varsa Dyazılsın; aksi takdirde D, giriş değerinin statik türü olur. Bir Deconstruct yöntem, bir yapısızlaştırma bildirimiyle aynı aşırı yükleme çözümleme kuralları kullanılarak D'den seçilir ve ek gereksinim, parametre sayısının outn'ye eşit olmasıdır; böyle bir yöntem yoksa derleme zamanı hatasıdır. Tür varsa, giriş değerinin statik türü türle uyumlu değilse (§11.2.2) derleme zamanı hatasıdır; çalışma zamanında giriş değeri türe göre test edilir ve bu test başarısız olursa konumsal desen eşleşmesi başarısız olur. Aksi takdirde, giriş değeri D'ye dönüştürülür ve seçilen Deconstruct yöntem parametrelerini alan out yeni değişkenlerle çağrılır. Alınan her değer karşılık gelen alt çizgiyle eşleştirilir ve bunların tümü başarılı olursa eşleşme başarılı olur. Herhangi bir alt belgenintanımlayıcısı varsa, bu tanımlayıcı parametreyi ilgili konumunda Deconstructadlandıracaktır.
  3. ITuple formu. Aksi takdirde, tür atlanırsa, hiçbir alt belgenintanımlayıcısı yoktur ve giriş değerinin objectstatik türü , System.Runtime.CompilerServices.ITupleveya örtük başvuru dönüştürmesi System.Runtime.CompilerServices.ITupleolan bir türdür. Bu durumda bu durum geçerlidir. Çalışma zamanında giriş değeri örneği olmayannullSystem.Runtime.CompilerServices.ITupleolarak test edilir; bu test başarısız olursa konumsal desen eşleşmesi başarısız olur. Aksi takdirde, değerin Length özelliği okunur ve n'ye eşit değilse konumsal desen eşleşmesi başarısız olur. Aksi takdirde, 1'den n'ye kadar her i için, giriş değeri i − 1 ile dizine eklenerek elde edilen değer, i. alt satırla eşleştirilir ve bunların tümü başarılı olursa eşleşme başarılı olur.
  4. Aksi takdirde, hiçbir durum geçerli değildir ve positional_pattern derleme zamanı hatasıdır.

Çalışma zamanında alt grafiklerin eşleşme sırası belirtilmemiştir ve başarısız bir eşleşme tüm alt grafiklerle eşleşmeye çalışmayabilir.

Örnek: Burada, bir ifade sonucunun yapısını kaldıracak ve sonuçta elde edilen değerleri ilgili iç içe yerleştirilmiş desenlerle eşleştireceğiz:

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

son örnek

Örnek: Tanımlama grubu öğelerinin ve Deconstruct parametrelerinin adları aşağıdaki gibi konumsal bir düzende kullanılabilir:

var numbers = new List<int> { 10, 20, 30 };
if (SumAndAverage(numbers) is (Sum: var sum, Average: var average))
{
    Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}; average is {average}");
}
else
{
    // Note: sum and average are in scope here, but not definitely assigned
    Console.WriteLine("No numbers provided to compute sum and average.");   
}

static (double Sum, double Average)? SumAndAverage(IEnumerable<int> numbers)
{
    int sum = 0;
    int count = 0;
    foreach (int number in numbers)
    {
        sum += number;
        count++;
    }
    return count == 0 ? null : (sum, sum / count);
}

Üretilen çıkış şu şekildedir:

Sum of [10 20 30] is 60; average is 20

son örnek

11.2.6 Özellik düzeni

property_pattern, giriş değerinin olup olmadığını nulldenetler ve erişilebilir özelliklerin veya alanların kullanımıyla ayıklanan değerlerle özyinelemeli olarak eşleşir.

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

Bir property_patternalt boyası subpattern_name içermiyorsa bu bir hatadır.

Tür null atanabilir bir değer türü (§8.3.12) veya null atanabilir başvuru türü (§8.9.3) ise derleme zamanı hatasıdır.

Not: Null denetim deseni önemsiz bir özellik deseninin dışında kalır. Dizenin s null olmadığını denetlemek için aşağıdaki formlardan herhangi birini yazabilirsiniz:

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

Bildirim x2 örneği, değişken türünün çıkarılması açısından benzerdir if (s is var x2) , ancak özellik deseni null olmayan bir değer olmasını x2 garanti eder. son not

E ifadesinin desen türü{alt desenleriyle} eşleşmesi göz önüne alındığında, e ifadesi türe göre belirlenen T türüyle desen uyumlu değilse (§11.2.2) derleme zamanı hatasıdır. Tür yoksa, türün statik e türü olduğu varsayılır. Alt yazılarının sol tarafında görünen her subpattern_name erişilebilir bir okunabilir özellik veya T alanı belirlemesi gerekir. property_pattern simple_designation varsa, T türünde bir desen değişkeni bildirir.

Çalışma zamanında ifade T'ye karşı test edilir. Bu başarısız olursa özellik deseni eşleşmesi başarısız olur ve sonuç olur false. Başarılı olursa, her property_subpattern alanı veya özelliği okunur ve değeri ilgili desenle eşleştirilir. Tüm eşleşmenin false sonucu yalnızca bunlardan herhangi birinin sonucu ise olur false. Alt yordamların eşleştirilme sırası belirtilmez ve başarısız bir eşleşme çalışma zamanında tüm alt yordamları test etmeyebilir. Eşleşme başarılı olursa ve property_pattern simple_designation bir single_variable_designation ise, bildirilen değişkene eşleşen değer atanır.

property_pattern, anonim türlerle desen eşleştirmek için kullanılabilir.

bir subpattern_name iç içe üyeye başvurabilir. Böyle bir durumda, her ad araması için alıcı, property_patterngiriş türünden başlayarak önceki T₀ üyesinin türüdür. T null atanabilir bir türse, T₀ onun temel türüdür, aksi takdirde T₀T'ye eşittir. Örneğin, formun { Prop1.Prop2: pattern } deseni tam olarak ile { Prop1: { Prop2: pattern } }eşdeğerdir.

Not: Bu, T null atanabilir bir değer türü veya başvuru türü olduğunda null denetimi içerir. Bu null denetim, kullanılabilir iç içe özelliklerin T'nin değil T₀'nin özellikleri olacağı anlamına gelir. Yinelenen üye yollarına izin verildiğinden, desen eşleştirmenin derlenmesi desenlerin ortak bölümlerinden yararlanabilir. son not

Örnek:

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

son örnek

Örnek: Aşağıdaki gibi, bir çalışma zamanı türü denetimi ve bir değişken bildirimi bir özellik desenine eklenebilir:

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

Üretilen çıkış şu şekildedir:

Hello
Hi!
12345
abc

son örnek

11.2.7 Atma düzeni

Her ifade atma deseni ile eşleşir ve bu da ifadenin değerinin atılmasıyla sonuçlanır.

discard_pattern
    : '_'
    ;

Eğer belirteç _ sabite veya türe simple_name (§12.8.4) olarak çözümlenebiliyorsa, bu durumda _ bir discard_pattern olarak işlem yapılmaz. Yerine:

  • Erişilebilir bir sabite çözümleniyorsa _ , _ sabit ifadesi bu sabit olan bir constant_pattern (§11.2.3) olarak yorumlanır.
  • Bir türe çözümleniyorsa _ , bir is işlecin sağ tarafında yapı relational_expressionis _ bu türe karşı is-type işleci (§12.15.12.1) testi olarak yorumlanır. Bir deseni kabul eden diğer söz dizimsel bağlamlarda, _ bir türe çözümlenmesi tek başına geçerli bir desen değildir; ancak, _bir declaration_pattern türü (örneğin, ) türü olarak veya bir _ x açıkça adlandıran diğer desen biçimlerinde görünebilir.

Bu kural, atma deseninin kullanıma sunulmasından önce tür veya tanımlayıcı olarak tanımlanan _ kodla geriye dönük uyumluluğu korur. Erişilebilir bir sabit veya tür (örneğin, yerel değişken, parametre, alan veya yöntem) dışında bir çözüme sahipse _ , kural uygulanmaz ve _discard_pattern kalır.

Not: Bu, var içindeki kuralına benzer, ancak _ kapsam içi sabit veya tür _ için hata oluşturmak yerine bu bildirime başvuru olarak yorumlanması gerekir. son not

Yukarıdaki kural uygulandıktan sonra belirteç _ hala bir discard_pattern ise, bu discard_pattern form relational_expression deseninin relational_expression tüm deseni olarak veya bir switch_labelis tüm deseni olarak görünmesi bir derleme zamanı hatasıdır. Ancak discard_pattern, kapsayan desenin alt kalemi olarak görünebilir (örneğin, bir positional_pattern veya property_patternalt kalemi olarak).

Not: Bu gibi durumlarda, herhangi bir ifadeyi eşleştirmek için at ile var _ kullanın. son not

Örnek:

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

Üretilen çıkış şu şekildedir:

5.0
0.0
0.0

Burada, numaralandırmanın karşılık gelen üyesine sahip olmayan herhangi bir tamsayı değerini işlemek null için bir atma deseni DayOfWeek kullanılır. Bu, ifadenin tüm olası giriş değerlerini işlemesini switch garanti eder. son örnek

Örnek: Aşağıda, adlı _ kapsam içi sabitin bir ifadedeki _ bir kolun yorumlanmasını switch nasıl değiştir aldığı gösterilmektedir. içindeWithoutUnderscore, kol bir _ ve herhangi bir değerle eşleşir. içinde WithUnderscorekapsam içi sabiti_, kolun _ yalnızca değeriyle eşleşen bir 0 olarak yorumlanmasına neden olur.

static string WithoutUnderscore(int n) => n switch
{
    1 => "one",
    _ => "other",
};

static string WithUnderscore(int n)
{
    const int _ = 0;
    return n switch
    {
        1 => "one",
        _ => "zero",
        var x => "other: " + x,
    };
}

son örnek

11.2.8 Tür deseni

Type_pattern, desen giriş değerinin (§11.1) belirli bir türe sahip olduğunu test etmek için kullanılır.

type_pattern
    : type
    ;

Türü adlandıran bir tür T deseni, deseni (§11.2.2) ile EE olan her tür T için geçerlidir.

Değerin çalışma zamanı türü , is-type işlecinde (§12.15.12.1) belirtilen kurallar kullanılarak türe göre test edilir. Test başarılı olursa, desen bu değerle eşleşir. Tür null atanabilir bir türse derleme zamanı hatasıdır. Bu desen formu hiçbir zaman bir değerle null eşleşmez.

11.2.9 İlişkisel desen

relational_pattern, desen giriş değerini (§11.1) sabit bir değerle ilişkisel olarak test etmek için kullanılır.

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

Sabit bir değere değerlendirmek için bir relational_pattern içindeki relational_expression gereklidir.

İlişkisel desenler, <<=> her iki işlenenin de aynı türe sahip olduğu ikili ilişkisel işleçleri destekleyen tüm yerleşik türler üzerinde , , ve ilişkisel işleçleri >=destekler: sbyte, byte, shortushort, , int, uint, longulongcharfloatdoubledecimalnintnuintve sabit listeleri.

türündeki her iki işlenenle de uygun bir yerleşik ikili ilişkisel işleç tanımlanmışsa veya sabit ifadenin türüne açık bir null atanabilir veya kutulanmamış dönüştürme varsaT, relational_pattern bir tür için TT.

İfade , double.NaNveya null sabit olarak değerlendirilirse float.NaNbu bir derleme zamanı hatasıdır.

Giriş değeri, uygun bir yerleşik ikili ilişkisel işlecin tanımlandığı bir türe sahip olduğunda, bu işlecin değerlendirilmesi ilişkisel desenin anlamı olarak alınır. Aksi takdirde, giriş değeri açık bir null atanabilir veya kutulanmamış dönüştürme kullanılarak sabit ifade türüne dönüştürülür. Böyle bir dönüştürme yoksa bu bir derleme zamanı hatasıdır. Dönüştürme başarısız olursa desenin eşleşmediği kabul edilir. Dönüştürme başarılı olursa, desen eşleştirme işleminin sonucu, dönüştürülen girişin ifadenin e «op» v değerlendirilmesinin e sonucudur; «op» ilişkisel işleç ve v sabit ifadedir.

Örnek:

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

Üretilen çıkış şu şekildedir:

Too high
Unknown
Acceptable

son örnek

11.2.10 Mantıksal desen

logical_pattern, bir desen eşleşmesinin sonucunu yok etmek veya bağlaç () veya ayrıştırma (andor) kullanarak birden çok desen eşleşmesinin sonuçlarını birleştirmek için kullanılır.

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, andve or topluca desen işleçleri olarak adlandırılır.

Negated_pattern, olumsuzlanan desen eşleşmiyorsa eşleşir ve tam tersi de geçerlidir. bir conjunctive_pattern her iki desenin de eşleşmesini gerektirir. disjunctive_pattern eşleşmesi için iki desen gerekir. Dil işleci karşılıklarının && aksine ve ||andor kısa devre işleçleri değildir.

Bir desen değişkeninin veya not desen işleci altında bildirilmesi derleme or zamanı hatasıdır.

Not: Bir notor desen değişkeni için kesin atama üretemediği veya üretemediği için, bu konumlarda bir tane bildirmek bir hatadır. son not

conjunctive_pattern ikinci desenin giriş türü, ilk deseninin and. Bir desenin P aşağıdaki gibi tanımlanır:

  • Tür deseni ise P , daraltılmış tür , tür deseninin türünün türüdür.
  • Aksi takdirde, bir bildirim deseni ise P , daraltılmış tür bildirim deseninin türünün türüdür.
  • Aksi takdirde, açık bir tür veren özyinelemeli bir desense P , daraltılmış tür bu türdür.
  • Aksi takdirde, bir P (ITuple) içindeki kurallarıyla eşleştirilirse , daraltılmış tür türüdürSystem.ITuple.
  • Aksi takdirde, sabitin null sabit olmadığı ve ifadenin Psabit ifade dönüştürmesinin olmadığı sabit bir desense, daraltılmış tür sabitin türüdür.
  • Aksi takdirde, sabit ifadenin Psabit ifade dönüştürmesinin olmadığı ilişkisel bir desense, daraltılmış tür sabitin türüdür.
  • Aksi takdirde, bir P desen iseor, daraltılmış tür, böyle bir ortak tür varsa, daraltılmış alt ekran türlerinin ortak türüdür. Bu amaçla, ortak tür algoritması yalnızca kimlik, kutulama ve örtük başvuru dönüştürmelerini dikkate alır ve bir desen dizisinin or tüm alt desenlerini (parantezli desenleri yoksayarak) dikkate alır.
  • Aksi takdirde, bir P desen iseand, dar türü doğru desenin daraltılmış türüdür. Ayrıca, sol desenin dar türü , sağ desenin giriş türüdür .
  • Aksi takdirde daraltılmış türüPP' nin giriş türüdür.

Not: Dil bilgisi tarafından belirtildiği gibi, not üzerinde önceliği andvardır ve bu öncelik üzerindedir or. Bu, parantezler kullanılarak açıkça gösterilebilir veya geçersiz kılınabilir. son not

sağ tarafında bir is göründüğünde, desenin kapsamı dil bilgisi tarafından belirlenir; sonuç olarak desen işleçleri , andve or desen içindeki desen işleçleri not, &&ve || desenin dışında mantıksal işleçlere !göre daha sıkı bağlanır.

Örnek:

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

Üretilen çıkış şu şekildedir:

High
Too low
Acceptable

son örnek

Örnek:

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

Üretilen çıkış şu şekildedir:

winter
autumn
spring

son örnek

Örnek:

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

// This is parsed as: (msg is (not int) or string)
bool 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
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}");

Üretilen çıkış şu şekildedir:

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

son örnek

11.2.11 Liste düzeni

list_pattern, bir listedeki veya dizideki bir öğe dizisiyle eşleşir.

list_pattern
    : list_pattern_clause simple_designation?
    ;

list_pattern_clause
    : '[' (pattern (',' pattern)* ','?)? ']'
    ;

list_pattern, hem sayılabilir (§18.1) hem de dizinlenebilir (§18.1) olan herhangi bir türle uyumludur; bağımsız değişken olarak alan Index erişilebilir bir dizin oluşturucuya veya tek int parametreli erişilebilir bir dizin oluşturucuya sahiptir. Her iki dizin oluşturucu da varsa, ilki tercih edilir. (Örtük dizin desteğinin ayrıntıları için bkz. §18.4.2 .)

Formun expr is [1, 2, 3] deseni aşağıdaki kodla eşdeğerdir:

expr.Length is 3
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Index(1, fromEnd: false)] is 2
&& expr[new Index(2, fromEnd: false)] is 3

Örnek:

int[] numbers = { 1, 2, 3 };

Console.WriteLine(numbers is [1, 2, 3]);  // True
Console.WriteLine(numbers is [1, 2, 4]);  // False
Console.WriteLine(numbers is [1, 2, 3, 4]);  // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3 and not 7]);  // True

son örnek

Atma düzeni (§11.2.7) tek bir öğeyle eşleşir.

Örnek:

List<int> numbers = new() { 1, 2, 3 };

if (numbers is [_, var second, _])
{
    Console.WriteLine($"The second element is {second}.");
}

son örnek

11.2.12 Dilim deseni

bir slice_pattern sıfır veya daha fazla öğe atar. Doğrudan bir list_pattern_clause ve ardından bu maddede en fazla bir kez kullanılacaktır.

slice_pattern
    : '..' pattern?
    ;

Alt ekran içermeyen bir slice_pattern , list_pattern ile uyumlu herhangi bir türle uyumludur. Alt kalemi olan bir slice_pattern, sayılabilir (§18.1) ve dilimlenebilir (§18.1) olan her türle uyumludur; bağımsız değişken olarak alan erişilebilir bir Range dizin oluşturucuya veya iki Slice parametreli erişilebilir int bir yönteme sahiptir. Her ikisi de varsa, ilk tercih edilir. (Örtük dizin desteğinin ayrıntıları için bkz. §18.4.2 .)

Bir slice_pattern uygun bir atılmış gibi davranır; yani, böyle bir düzen için test yapılmaz. Bunun yerine, yalnızca uzunluk ve dizin oluşturucu olarak diğer düğümleri etkiler. Örneğin, formun expr is [1, .. var s, 3] deseni aşağıdaki koda eşdeğerdir (açık Index ve Range destek yoluyla uyumluysa):

expr.Length is >= 2
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))] is var s
&& expr[new Index(1, fromEnd: true)] is 3

bir slice_pattern giriş türü, iki özel durumla birlikte temel alınan this[Range] veya Slice yöntemin dönüş türüdür: s ve diziler string için string.Substringve RuntimeHelpers.GetSubArraysırasıyla kullanılacaktır.

Örnek: Dilim deseni, öğeleri yalnızca giriş dizisinin başında veya/ve sonunda eşleştirmek için kullanılabilir.

Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]);  // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]);  // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]);  // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]);  // False

Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]);  // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]);  // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]);  // True

Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]);  // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]);  // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]);  // False

son örnek

Örnek: Bir alt desen, bir dilim deseni içinde iç içe yerleştirilebilir:

MatchMessage("aBBA");  // output: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // output: Message apron doesn't match.

void MatchMessage(string message)
{
    var result = message is ['a' or 'A', .. var s, 'a' or 'A']
        ? $"Message {message} matches; inner part is {s}."
        : $"Message {message} doesn't match.";
    Console.WriteLine(result);
}

Validate(new[] { -1, 0, 1 });     // output: not valid
Validate(new[] { -1, 0, 0, 1 });  // output: valid

void Validate(int[] numbers)
{
    var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0]
        ? "valid" : "not valid";
    Console.WriteLine(result);
}

son örnek