Der Musterabgleich ist eine Funktion, mit der ein Ausdruck auf das Auftreten eines bestimmten Musters getestet werden kann. Es ist ein Merkmal, das in funktionalen Sprachen häufiger vorkommt . Der Musterabgleich ist von Natur aus boolesch, was impliziert, dass es zwei mögliche Ergebnisse gibt: entweder der Ausdruck stimmt mit dem Muster überein oder nicht. Dieses Feature wurde erstmals in C# 7.0 eingeführt und hat dann in aufeinanderfolgenden Versionen der Sprache eine Reihe von Verbesserungen erfahren. 

Der Musterabgleich ermöglicht Vorgänge wie Typprüfung (Typmuster), Nullprüfung (konstantes Muster), Vergleiche (relationales Muster), Prüfen und Vergleichen von Werten von Eigenschaften (Eigenschaftsmuster), Objektdekonstruktion (Positionsmuster) und Wiederverwendung von Ausdrücken mithilfe der Variablenerstellung ( var -Muster), das mit minimaler und prägnanter Syntax ausgedrückt werden muss. Darüber hinaus können diese Muster verschachtelt sein und mehrere Teilmuster umfassen. Muster können auch mit Musterkombinatoren (und, oder und nicht) kombiniert werden. C# ermöglicht den Musterabgleich durch drei Konstrukte:

1. ist Betreiber 

Vor C# 7.0 wurde der einzige Zweck des is-Operators verwendet, um zu prüfen, ob ein Objekt mit einem bestimmten Typ kompatibel ist. Seit C# 7.0 wurde der is-Operator erweitert, um zu testen, ob ein Ausdruck mit einem Muster übereinstimmt.

Syntax:

Ausdruck ist Muster

2. switch-Anweisungen

So wie eine switch-Anweisung verwendet werden kann, um eine Codeverzweigung (case) auszuführen, indem ein Ausdruck auf eine Menge von Werten getestet wird, kann sie auch verwendet werden, um eine Codeverzweigung auszuführen, indem ein Ausdruck auf das Auftreten einer Menge von Werten getestet wird Muster.

Syntax:

Schalter (Ausdruck)

{

    Fallmuster1:

    // auszuführender Code



    // wenn Ausdruck mit Muster1 übereinstimmt

    brechen;

    Fallmuster2:

 

    // auszuführender Code

    // wenn Ausdruck mit Muster2 übereinstimmt

    brechen;

    …

    FallmusterN:

 

    // auszuführender Code

    // wenn Ausdruck mit MusterN übereinstimmt

    brechen;

    Ursprünglich:

    // Code, der ausgeführt werden soll, wenn Ausdruck

    // stimmt mit keinem der obigen Muster überein  

}

3. Ausdrücke wechseln 

Eine Reihe von Mustern kann auch mit einem Switch-Ausdruck getestet werden , um einen Wert basierend darauf auszuwählen, ob das Muster übereinstimmt.

Syntax:

Ausdruck wechseln

{

    Muster1 => Wert1,

    Muster2 => Wert2,

    …

    MusterN => WertN,

    _ => Standardwert

}

Von C# unterstützte Muster

Ab C# 9 werden die folgenden Muster von der Sprache unterstützt. 

  • Geben Sie Muster ein
  • Beziehungsmuster
  • Eigenschaftsmuster
  • Positionsmuster
  • var-Muster
  • Konstantes Muster

C# unterstützt auch die Verwendung der folgenden Konstrukte mit Musterabgleich:

  • Variablendeklarationen
  • Musterkombinatoren ( und , oder und nicht )
  • Variablen verwerfen ( _ )
  • Verschachtelte Muster oder Teilmuster

Das Typenmuster

Das Typmuster kann verwendet werden, um zu prüfen, ob der Laufzeittyp eines Ausdrucks mit dem angegebenen Typ übereinstimmt oder mit diesem Typ kompatibel ist. Wenn der Ausdruck, d. h. der abgeglichene Wert, mit dem im Muster angegebenen Typ kompatibel ist, ist der Abgleich erfolgreich. Das Typmuster kann optional auch eine Variablendeklaration enthalten. Wenn der getestete Wert mit dem Typ übereinstimmt, wird er in diesen Typ umgewandelt und dann dieser Variablen zugewiesen. Variablendeklarationen in Mustern werden weiter beschrieben.

Syntax:

// Wird in C# 9 und höher verwendet

Modellname 

// Wird in C# 7 verwendet

TypeName-Variable

Modellname _

Beispiel:

C#

// C# program to illustrate the concept of Type Pattern
using System;
  
public class GFG{
      
static void PrintUppercaseIfString(object arg)
{
    // If arg is a string:
    // convert it to a string
    // and assign it to variable message
    if (arg is string message) 
    {
        Console.WriteLine($"{message.ToUpper()}");
    }
    else
    {
        Console.WriteLine($"{arg} is not a string");
    }
}
  
// Driver code
static public void Main()
{
    string str = "Geeks For Geeks";
    int number = 42;
    object o1 = str;
    object o2 = number;
  
    PrintUppercaseIfString(o1);
    PrintUppercaseIfString(o2);
}
}
Ausgabe

GEEKS FÜR GEEKS
42 ist keine Zeichenfolge

Im obigen Beispiel akzeptiert die Methode PrintUppercaseIfString() ein Argument vom Typ object namens arg . Jeder Typ in C# kann in ein Objekt umgewandelt werden, da in C# alle Typen von Objekten abgeleitet werden. Dies wird als Typenvereinigung bezeichnet .

Automatisches Gießen

Wenn arg eine Zeichenkette ist, wird sie von Objekt zu Zeichenkette umgewandelt und einer Variablen namens Nachricht zugewiesen . Wenn arg kein String , sondern ein anderer Typ ist, wird der else -Block ausgeführt. Daher werden sowohl die Typprüfung als auch die Umwandlung in einem Ausdruck kombiniert. Wenn der Typ nicht übereinstimmt, wird die Variable nicht erstellt. 

Types mit dem Type Pattern einschalten

Das Typmuster, das mit einer switch- Anweisung verwendet wird, kann helfen, einen Codezweig ( case branch) abhängig vom Werttyp auszuwählen. Der folgende Code definiert eine Methode namens PrintType() , die ein Argument als Objekt akzeptiert und dann verschiedene Nachrichten für verschiedene Arten von Argumenten ausgibt:

C#

// C# program to illustrate the concept of Type Pattern Switch
using static System.Console;
  
// Allows using WriteLine without Console. prefix
public class Person
{
    public string Name
    {
        get;
        set;
    }
}
  
class GFG{
      
static void PrintType(object obj)
{
    switch (obj)
    {
      case Person p:
          WriteLine("obj is a Person");
          WriteLine($"Name of the person: {p.Name}");
          break;
  
      case int i:
          WriteLine("obj is an int");
          WriteLine($"Value of the int: {i}");
          break;
  
      case double d:
          WriteLine("obj is a double");
          WriteLine($"Value of the double: {d}");
          break;
  
      default:
          WriteLine("obj is some other type");
          break;
    }
  
    WriteLine(); // New line
}
  
// Driver code
static public void Main()
{
    var person = new Person { Name = "Geek" };
  
    PrintType(42);
    PrintType(person);
    PrintType(3.14);
    PrintType("Hello");
}
}

Ausgabe:

obj is an int
Value of the int: 42

obj is a Person
Name of the person: Geek

obj is a double
Value of the double: 3.14

obj is some other type

Beziehungsmuster

Relationale Muster wurden in C# 9 eingeführt. Sie helfen uns, Vergleiche für einen Wert durchzuführen, indem wir Folgendes verwenden: <(kleiner als), <=(kleiner als oder gleich), >(größer als) und >=(größer als oder gleich). ) Operatoren.

Syntax:

< konstant

<= konstant



> konstant

>= konstant

Beispiel:

C#

// Program to check if a number is positive,
// negative or zero using relational patterns
// using a switch statement
using System;
  
class GFG{
      
public static string GetNumberSign(int number)
{
    switch (number)
    {
        case < 0:
            return "Negative";
        case 0:
            return "Zero";
        case >= 1:
            return "Positive";
    }
}
  
// Driver code
static public void Main()
{
    int n1 = 0;
    int n2 = -31;
    int n3 = 18;
      
    Console.WriteLine(GetNumberSign(n1));
    Console.WriteLine(GetNumberSign(n2));
    Console.WriteLine(GetNumberSign(n3));
}
}

Ausgabe:

Zero
Negative
Positive

Das obige Beispiel kann mit einem switch-Ausdruck prägnanter geschrieben werden :

C#

// Program to check if a number
// is positive, negative or zero
// using relational patterns
// with a switch expression
using System;
  
class GFG{
      
public static string GetNumberSign(int number)
{
    return number switch
    {
        < 0 => "Negative", 
        0 => "Zero", 
        >= -1 => "Positive"
    };
}
  
// Driver code
static public void Main()
{
    int n1 = 0;
    int n2 = -31;
    int n3 = 18;
      
    Console.WriteLine(GetNumberSign(n1));
    Console.WriteLine(GetNumberSign(n2));
    Console.WriteLine(GetNumberSign(n3));
}
}

Ausgabe:

Zero
Negative
Positive

In ähnlicher Weise können auch relationale Muster mit dem is -Operator verwendet werden:

int n = 2;
Console.WriteLine(n is <= 10); // Prints true
Console.WriteLine(n is > 5); // Prints false

Dies ist möglicherweise nicht so nützlich, da n ist <= 10 dasselbe ist wie das Schreiben von n <= 10 . Diese Syntax ist jedoch mit Musterkombinatoren bequemer (wird weiter diskutiert).  

Eigenschaftsmuster

Eigenschaftsmuster ermöglichen übereinstimmende Werte von Eigenschaften, die für ein Objekt definiert sind. Das Muster gibt den Namen der abzugleichenden Eigenschaft und dann nach einem Doppelpunkt ( : ) den Wert an, der übereinstimmen muss. Mehrere Eigenschaften und ihre Werte können durch Kommas getrennt angegeben werden.

Syntax:

{ Property1: value1, Property2 : value2, …, PropertyN: valueN }

Eine solche Syntax erlaubt uns zu schreiben:

„Geeks“ ist { Länge: 4 }

Anstatt:

„Geeks“.Länge == 4

Beispiel:

C#

// C# program to illustrate the concept of Property Pattern
using System;
  
class GFG{
  
public static void DescribeStringLength(string str)
{
      
    // Constant pattern, discussed further
    if (str is null) 
    {
        Console.WriteLine("Null string");
    }
  
    if (str is { Length: 0 })
    {
        Console.WriteLine("Empty string");
        return;
    }
  
    if (str is { Length: 1 })
    {
        Console.WriteLine("String of length 1");
        return;
    }
  
    Console.WriteLine("Length greater than 1");
    return;
}
  
// Driver code
static public void Main()
{
    DescribeStringLength("Hello!");
    Console.WriteLine();
    DescribeStringLength("");
    Console.WriteLine();
    DescribeStringLength("X");
    Console.WriteLine();
}
}

Ausgabe:

Length greater than 1
Empty string
String of length 1

Positionsmuster

Positionsmuster ermöglichen die Angabe einer Reihe von Werten in Klammern und stimmen überein, wenn jeder Wert in den Klammern mit den Werten des übereinstimmenden Objekts übereinstimmt. Die Objektwerte werden durch Dekonstruktion extrahiert . Positionsmuster basieren auf dem Dekonstruktionsmuster. Die folgenden Typen können Positionsmuster verwenden:

Syntax:

(Konstante1, Konstante2, …)

Beispiel 1: Positionsmuster mit einem Typ, der eine Deconstruct()- Methode definiert

Der folgende Code definiert zwei Funktionen LogicalAnd() und LogicalOr() , die beide ein Objekt von BooleanInput akzeptieren. BooleanInput ist ein Werttyp (Struktur), der zwei boolesche Eingabewerte darstellt. Die Methoden verwenden diese beiden Eingabewerte und führen an diesen Werten eine logische UND- und eine logische ODER-Operation durch. C# hat bereits logische AND(&&)- und logische OR(||)-Operatoren, die diese Operationen für uns ausführen. Die Methoden in diesem Beispiel implementieren diese Operationen jedoch manuell, um Positionsmuster zu demonstrieren.

C#

// C# program to illustrate the concept of Positional Pattern
using System;
  
// Represents two inputs to the truth table
public struct BooleanInput
{
    public bool Input1
    {
        get;
        set;
    }
  
    public bool Input2
    {
        get;
        set;
    }
  
    public void Deconstruct(out bool input1, 
                            out bool input2)
    {
        input1 = Input1;
        input2 = Input2;
    }
}
  
class GFG{
      
// Performs logical AND on an input object
public static bool LogicalAnd(BooleanInput input)
{
      
    // Using switch expression
    return input switch
    {
        (false, false) => false, 
        (true, false) => false, 
        (false, true) => false, 
        (true, true) => true
    };
}
  
// Performs logical OR on an input object
public static bool LogicalOr(BooleanInput input)
{
      
    // Using switch statement
    switch (input)
    {
        case (false, false):
            return false;
        case (true, false):
            return true;
        case (false, true):
            return true;
        case (true, true):
            return true;
    }
}
  
// Driver code
static public void Main()
{
    var a = new BooleanInput{Input1 = true, 
                             Input2 = false};
    var b = new BooleanInput{Input1 = true, 
                             Input2 = true};
    
    Console.WriteLine("Logical AND:");
    Console.WriteLine(LogicalAnd(a));
    Console.WriteLine(LogicalAnd(b));
    
    Console.WriteLine("Logical OR:");
    Console.WriteLine(LogicalOr(a));
    Console.WriteLine(LogicalOr(b));
}
}

Ausgabe:

Logical AND:
False
True
Logical OR:
True
True

Beispiel 2: Verwenden von Positionsmustern mit Tupeln

Jede Instanz von System.ValueTuple kann in Positionsmustern verwendet werden. C# bietet eine Kurzsyntax zum Erstellen von Tupeln mit runden Klammern:(). Ein Tupel kann schnell im laufenden Betrieb erstellt werden, indem ein Satz bereits deklarierter Variablen in Klammern gesetzt wird. Im folgenden Beispiel akzeptiert die LocatePoint()- Methode zwei Parameter, die die x- und y-Koordinaten eines Punkts darstellen, und erstellt dann mithilfe eines zusätzlichen Klammerpaars ein Tupel nach dem switch -Schlüsselwort. Die äußeren Klammern sind Teil der switch- Anweisungssyntax, die inneren Klammern erzeugen das Tupel unter Verwendung der x- und y - Variablen.

C#

// C# program to illustrate the concept of Positional Pattern
using System;
  
class GFG{
      
// Displays the location of a point
// by accepting its x and y coordinates
public static void LocatePoint(int x, int y)
{
    Console.WriteLine($"Point ({x}, {y}):");
      
    // Using switch statement
    // Note the double parantheses
    switch ((x, y)) 
    {
        case (0, 0):
            Console.WriteLine("Point at origin");
            break;
        case (0, _): // _ will match all values for y
            Console.WriteLine("Point on Y axis");
            break;
        case (_, 0):
            Console.WriteLine("Point on X axis");
            break;
        default:
            Console.WriteLine("Point elsewhere");
            break;
    }
}
  
// Driver code
static public void Main()
{
    LocatePoint(10, 20);
    LocatePoint(10, 0);
    LocatePoint(0, 20);
    LocatePoint(0, 0);
}
}

Ausgabe:

Point (10, 20):
Point elsewhere
Point (10, 0):
Point on X axis
Point (0, 20):
Point on Y axis
Point (0, 0):
Point at origin

Konstantes Muster

Das konstante Muster ist die einfachste Form eines Musters. Es besteht aus einem konstanten Wert. Es wird geprüft, ob der abgeglichene Ausdruck gleich dieser Konstante ist. Die Konstante kann sein:

Das konstante Muster erscheint normalerweise als Teil anderer Muster als Untermuster (wird weiter besprochen), kann aber auch alleine verwendet werden.

Einige Beispiele für das konstante Muster, das mit dem is - Operator verwendet wird, wären: 

expression is 2 // int literal
expression is "Geeks" // string literal
expression is System.DayOfWeek.Monday // enum
expression is null  // null

Beachten Sie das letzte Beispiel, in dem das Muster null ist . Dies impliziert, dass der Musterabgleich eine weitere Möglichkeit bietet, zu prüfen, ob ein Objekt null ist. Außerdem ist expression is null möglicherweise besser lesbar und intuitiver als der typische Ausdruck == null .

Im Kontext einer switch- Anweisung sieht das konstante Muster genauso aus wie eine reguläre switch- Anweisung ohne Musterabgleich.

Beispiel:

Das folgende Beispiel verwendet einen Switch- Ausdruck mit dem konstanten Muster in einer Methode namens DayOfTheWeek() , die den Namen des Wochentags aus der übergebenen Zahl zurückgibt. 

C#

// C# program to illustrate the concept of Constant Pattern
using System;
  
class GFG{    
  
// Returns the name of the day of the week
public static string DayOfTheWeek(int day)
{
      
    // Switch expression
    return day switch 
    {
        1 => "Sunday",
        2 => "Monday",
        3 => "Tuesday",
        4 => "Wednesday",
        5 => "Thursday",
        6 => "Friday",
        7 => "Saturday",
        _ => "Invalid week day"
    };
}
  
// Driver code
static public void Main()
{
    Console.WriteLine(DayOfTheWeek(5));
    Console.WriteLine(DayOfTheWeek(3));
}
}

Ausgabe:

Thursday
Tuesday

Das var -Muster

Das var -Muster funktioniert etwas anders als andere Muster. Eine var -Musterübereinstimmung ist immer erfolgreich, was bedeutet, dass das Übereinstimmungsergebnis immer wahr ist. Der Zweck des var -Musters besteht nicht darin, einen Ausdruck auf ein Muster zu testen, sondern einen Ausdruck einer Variablen zuzuweisen. Dies ermöglicht die Wiederverwendung der Variablen in aufeinanderfolgenden Ausdrücken. Das var -Muster ist eine allgemeinere Form des Typmusters. Es ist jedoch kein Typ angegeben; Stattdessen wird var verwendet, sodass keine Typprüfung stattfindet und die Übereinstimmung immer erfolgreich ist .

Syntax:

var varName

var (varName1, varName2, …)

Betrachten Sie den folgenden Code, in dem Tag und Monat eines DateTime -Objekts verglichen werden müssen:

var now = DateTime.Now;
if (now.Month > 6 && now.Day > 15)
{
    // Do Something
}

Dies kann mit dem var -Muster in einer Zeile geschrieben werden :

if (DateTime.Now is var now && now.Month > 6 && now.Day > 15)
{
    // Do Something
}

Musterkombinatoren / Logische Muster

C# 9 hat auch Musterkombinatoren eingeführt. Musterkombinatoren ermöglichen das Kombinieren mehrerer Muster miteinander. Das Folgende sind die Musterkombinatoren:

  • Negatives Muster: nicht
  • Konjunktivmuster: und
  • Disjunktives Muster bzw
KombinatorStichwortBeschreibungBeispiel
Negatives MusternichtKehrt eine Musterübereinstimmung um

nicht 2

nicht < 10

nicht null

Konjunktives MusterundÜbereinstimmungen, wenn beide Muster übereinstimmen

> 0 und < 10

{ Jahr: 2002 } und { Monat: 1 }

nicht int und nicht double

Disjunktives MusteroderÜbereinstimmungen, wenn mindestens eines der Muster übereinstimmt

„Hallo“ oder „Hallo“ oder „Hey“

null oder (0, 0)

{ Jahr: 2004 } oder { Jahr: 2002 }

Musterkombinatoren sind logischen Operatoren (!, &&, ||) sehr ähnlich , aber die Operanden sind Muster anstelle von Bedingungen oder booleschen Ausdrücken. Kombinatoren machen den Musterabgleich flexibler und helfen auch, einige Tastenanschläge einzusparen.

Einfachere Vergleiche

Durch die Verwendung von Musterkombinatoren mit dem relationalen Muster kann ein Ausdruck mit mehreren anderen Werten verglichen werden, ohne den Ausdruck immer wieder zu wiederholen. Betrachten Sie zum Beispiel Folgendes:

int number = 42;
if (number > 10 && number < 50 && number != 35) 
{
    // Do Something
}

Mit Musterabgleich und Kombinatoren kann dies vereinfacht werden:

int number = 42;
if (number is > 10 and < 50 and not 35)
{
   // Do Something
}

Wie ersichtlich, muss die Nummer des Variablennamens nicht wiederholt werden; Vergleiche können nahtlos verkettet werden.

Prüfen, ob ein Wert nicht null ist

Im obigen Abschnitt über konstante Muster wurde eine alternative Methode zum Überprüfen, ob ein Wert null ist, besprochen. Musterkombinatoren bieten ein Gegenstück, mit dem überprüft werden kann, ob ein Wert nicht null ist:

if (expression is not null) 
{
}

Beispiel:

Das folgende Beispiel definiert eine Methode namens I sVowel() , die prüft, ob ein Zeichen ein Vokal ist oder nicht, indem der Musterkombinator oder verwendet wird, um mehrere konstante Muster zu kombinieren:

C#

// C# program to illustrate the concept of Pattern Combinators
using System;
  
class GFG{
      
public static bool IsVowel(char c)
{
    return char.ToLower(c) is 'a' or 'e' or 'i' or 'o' or 'u';
}
  
// Driver code
public static void Main()
{
    Console.WriteLine(IsVowel('A'));
    Console.WriteLine(IsVowel('B'));
    Console.WriteLine(IsVowel('e'));
    Console.WriteLine(IsVowel('x'));
    Console.WriteLine(IsVowel('O'));
    Console.WriteLine(IsVowel('P'));
}
}

Ausgabe:

True
False
True
False
True
False

Variablendeklarationen

Einige Muster unterstützen das Deklarieren einer Variablen nach dem Muster. 

Typmuster: Variablendeklarationen in Typmustern sind eine bequeme Möglichkeit, sowohl eine Typprüfung als auch eine Umwandlung in einem Schritt zu kombinieren.

Folgendes berücksichtigen:

object o = 42;
if (o is int)
{
    int i = (int) o;
    //...
}

Dies kann mit einer Variablendeklaration auf einen einzigen Schritt reduziert werden:

object o = 42;
if (o is int i)
{
    //...
}

Positions- und Eigenschaftsmuster: Positions- und Eigenschaftsmuster erlauben auch eine Variablendeklaration nach dem Muster:

if (DateTime.Now is { Month: 12 } now)
{
    // Do something with now
}
var p = (10, 20);
if (p is (10, 20) coords)
{
   // Do something with coords
}

Hier enthalten p und coords den gleichen Wert und coords sind möglicherweise von geringem Nutzen. Aber die obige Syntax ist zulässig und kann manchmal mit einem Objekt nützlich sein, das eine Deconstruct()- Methode definiert. 

Hinweis: Variablendeklarationen sind nicht erlaubt, wenn die Musterkombinatoren or und not verwendet werden, aber sie sind mit and erlaubt .

Variable Verwerfungen

Manchmal ist der den Variablen während des Musterabgleichs zugewiesene Wert möglicherweise nicht hilfreich. Variablenverwerfungen ermöglichen das Ignorieren der Werte solcher Variablen. Ein Verwerfen wird durch einen Unterstrich ( _ ) dargestellt.

In Typmustern: Bei Verwendung von Typmustern mit Variablendeklarationen wie im folgenden Beispiel:

switch (expression)
{
    case int i:
        Console.WriteLine("i is an integer");
        break;
    ...
}

die Variable i wird nie verwendet. Es kann also verworfen werden:

case int _: 

Ab C# 9 ist es möglich, Typmuster ohne Variable zu verwenden, wodurch auch der Unterstrich entfernt werden kann:

case int:

In Positionsmustern: Bei der Verwendung von Positionsmustern kann ein Verwerfungszeichen als Platzhalterzeichen verwendet werden, um alle Werte an bestimmten Positionen abzugleichen. Wenn wir zum Beispiel im obigen Punkt -Beispiel abgleichen möchten, wenn die x-Koordinate 0 ist und die y-Koordinate keine Rolle spielt, was bedeutet, dass das Muster unabhängig von der y-Koordinate abgeglichen werden muss, kann Folgendes sein fertig:

point is (0, _) // will match for all values of y

Mehrere Muster ohne Kombinatoren 

Es ist möglich, ein Typmuster, ein Positionsmuster und ein Eigenschaftsmuster zusammen ohne Kombinatoren zu verwenden.

Syntax:

Typmuster Positionsmuster Eigenschaftsmuster Variablenname

Betrachten Sie die Point -Struktur:

struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
    public string Name { get; set; }
    public void Deconstruct(out int x, out int y)
    {
        x = X;
        y = Y;    
    }
}
...
object o = Point() { X = 10, Y = 20, Name = "A" };

Anstatt:

if (o is Point p and (10, _) and { Y: 20}) {..}

Folgendes kann geschrieben werden:

if (o is Point (10, _) { Y: 20 } p) {..}

Eines oder mehrere der Muster können weggelassen werden. Es muss jedoch mindestens ein Muster vorhanden sein, und die Reihenfolge bei der Verwendung mehrerer Muster zusammen muss dieselbe wie oben sein. Illegal ist beispielsweise Folgendes:

if (o is (10, _) Point { Y: 20 } p)

Verschachtelte Muster / Untermuster

Ein Muster kann aus mehreren Untermustern bestehen. Neben der Möglichkeit, mehrere Muster mit Musterkombinatoren zu kombinieren, ermöglicht C# auch, dass ein einzelnes Muster aus mehreren inneren Mustern besteht.  

Beispiele:

Betrachten Sie die obige Point -Struktur und das folgende Objekt point :

Point point = new Point() { X = 10, Y = 20, Name = "B" };

Geben Sie Pattern und var Pattern in ein Eigenschaftsmuster ein

if (point is { X: int x, Y: var y }) { .. }

Geben Sie Pattern und var Pattern in einem Positionsmuster ein

if (point is (int x, var y)) { .. }

Relationales Muster in einem Positionsmuster und einem Eigenschaftsmuster

switch (point) 
{
    case (< 10, <= 15): 
         .. 
         break;
    case { X: < 10, Y: <= 15 }:
         ..
         break;
    ..
}

Betrachten Sie für das nächste Beispiel die folgenden Objekte:

var p1 = new Point { X = 0, Y = 1, Name = "X" };
var p2 = new Point { X = 0, Y = 2, Name = "Y" };

Eigenschaftsmuster in einem Positionsmuster

if ((p1, p2) is ({ X: 0 }, { X: 0 })) { .. }