Listen- und Datenschnittmuster

Tip

Dieser Artikel ist Teil des Abschnitts "Grundlagen" für Entwickler, die bereits mindestens eine Programmiersprache kennen und C# erlernen. Beginnen Sie mit der Übersicht über den Musterabgleich , wenn Muster für Sie neu sind. Vollständige unterstützte Typen- und Sprachregeln finden Sie unter Listenmuster in der Sprachreferenz.

Die Form einer Sequenz ist der Satz feststellbarer Eigenschaften, die ein Muster erfordert. Diese Eigenschaften können die Anzahl der Elemente, anforderungen, die für jedes Element oder für eine Abfolge von Elementen als Ganzes geschrieben wurden, sowie Markerwerte bei bestimmten Indizes enthalten. Beispielsweise kann ein Shape genau zwei Elemente mit "Name" an Index 0 erfordern, oder ein erstes Markierungselement, ein letztes Markierungselement und eine nichtleere Sequenz dazwischen.

Ein Listenmuster beschreibt eine Form durch die Kombination einer Anforderung an die Anzahl der Elemente mit geschachtelten Mustern an geordneten Positionen. Es testet nur die Anforderungen, die im Muster geschrieben wurden: Ein Element-Unterpattern testet das entsprechende Element, während ein Segmentmuster eine Sequenz von anderen nicht übereinstimmenden Elementen zulassen oder testen kann. Sie können diese Teile verwenden, um eine genaue Anzahl und Markierungswerte abzugleichen, Werte an festen Positionen zu erfassen, eine nicht übereinstimmende Mitte zuzulassen oder ein geschachteltes Muster auf diese Mitte anzuwenden.

Wählen Sie ein Listenmuster aus, wenn der Kompilierzeittyp der Eingabe eine Length- oder Count-Eigenschaft sowie indizierten Elementzugriff bereitstellt, der ein Element anhand seiner Position abruft, wie in input[index]. Arrays, List<T>, Zeichenfolgen und Spannen sind gängige Beispiele. Der Compiler bestimmt die Eignung anhand des deklarierten Typs der Variablen zur Kompilierzeit, da er diese erforderlichen Member auflösen muss, bevor das Programm ausgeführt wird. Die IEnumerable<T>-Schnittstelle selbst bietet eine Aufzählung anstelle dieser Member, auch wenn das Laufzeitobjekt eine indizierbare Auflistung ist.

Listenmuster verwenden eine Länge oder Anzahl sowie indizierten Zugriff auf Elemente anstelle einer Aufzählung. Bei gängigen integrierten Typen kann der Abgleich nur die Positionen überprüfen, die durch das Muster benannt werden, anstatt durch jedes Element zu durchlaufen. Die Kosten dieser Vorgänge hängen vom Eingabetyp ab. Das Durchlaufen einer langen Sammlung kann viel Zeit in Anspruch nehmen. Verwenden Sie daher eine Schleife oder LINQ, wenn für die Entscheidung eine beliebige Anzahl von Elementen statt bestimmter Positionen untersucht werden muss.

Eine exakte Form abgleichen

Die folgende Methode erkennt eine zweispaltige Kopfzeile:

static bool IsHeader(string[] columns) =>
    columns is ["Name", "Score"];

Der columns Ausdruck ist die Mustereingabe. ["Name", "Score"] enthält zwei Konstantenmuster. Ein genaues Listenmuster lässt ein Segmentmuster weg, erfordert genau zwei Elemente und wendet jedes geschachtelte Muster auf das Element am gleichen Index an. Dieses Muster beschreibt eine Form mit einer genauen Anzahl und zwei Markierungswerten: "Name" bei Index 0 und "Score" bei Index 1. Geschachtelte Elementmuster sind optional: Das leere Listenmuster [] beschreibt und stimmt mit einer Sequenz ohne Elemente überein.

Wählen Sie ein Listenmuster aus, wenn das Shape eine Elementanzahl mit Anforderungen an sortierten Positionen kombiniert. Wenn nur die Anzahl der Elemente von Bedeutung ist, bringt ein Eigenschaftsmuster vom Typ Length oder Count, wie etwa items is { Count: 0 }, diese Absicht direkter zum Ausdruck.

Verwenden Sie ein Discard, um einen beliebigen Elementwert abzugleichen

Die folgende Methode liest den Gewinner und den Drittplatzierten aus einer Zieleinlaufreihenfolge mit drei Namen:

static string GetAnnouncements(List<string> finishingOrder) =>
    finishingOrder switch
    {
        [var winner, _, var thirdPlace] =>
            $"Winner: {winner}; third place: {thirdPlace}",
        _ => "A complete three-runner result isn't available"
    };

Die Muster var winner und var thirdPlace deklarieren jeweils eine Variable. Wenn das Listenmuster passt, weist C# der entsprechenden Variablen den Wert des übereinstimmenden Elements an dieser Position zu, sodass das Ergebnis thirdPlace und winner verwenden kann. Das Verwerfenmuster _ akzeptiert das zweite Element und verwirft seinen Wert. Diese Form erfordert genau drei Elemente und weist der ersten und dritten Position eine spezifische Bedeutung zu, schreibt jedoch an keiner Position bestimmte Werte vor.

Wählen Sie dieses Formular aus, wenn feste Positionen eine stabile Bedeutung haben. Verwenden Sie eine Schleife oder LINQ, wenn Sie eine beliebige Anzahl von Elementen untersuchen müssen, eine Sequenz transformieren, in der gesamten Schleife suchen oder Aggregation durchführen müssen.

Verbleibende Elemente mit einem Segmentmuster zulassen

In diesem vereinfachten Beispiel kann eine Befehlszeile mit --verbose beginnen und andere Argumente enthalten, und es wird davon ausgegangen, dass sie mit dem Eingabedateinamen endet. Die folgende Methode erkennt Shapes mit einem Dateinamen an der letzten Position und erfasst diesen Wert:

static string GetInputFile(string[] arguments) =>
    arguments switch
    {
        ["--verbose", .., var fileName] => $"Verbose processing: {fileName}",
        [.., var fileName] => $"Processing: {fileName}",
        [] => "No input file was provided"
    };

Das Segmentmuster.. ermöglicht null oder mehr verbleibende Elemente zwischen den Mustern des ersten und letzten Elements. Ein Listenmuster kann höchstens ein Segmentmuster enthalten. Der erste Schalterarm beschreibt eine Form mit mindestens zwei Elementen: die Markierung "--verbose" bei Index 0, einen Dateinamen an der letzten Position und eine beliebige Anzahl nicht übereinstimmender Argumente dazwischen. Das eigenständige Segment testt diese mittleren Argumente nicht. Der zweite Arm akzeptiert alle nicht leeren Formen und erfasst das letzte Element, während das leere Muster eine Sequenz ohne Elemente behandelt.

Ein Segment kann am Anfang, in der Mitte oder am Ende eines Listenmusters angezeigt werden. Verwenden Sie sie, wenn eine Sequenz variabler Länge Teil der Form ist, aber nur die umgebenden Positionen Elementprüfungen benötigen. Verwenden Sie gewöhnliche Iteration, wenn jedes Element eine Verarbeitung benötigt.

Anwenden eines Musters auf ein Segment

Sie können ein weiteres Muster auf den Teil anwenden, der mit .. übereinstimmt. Die folgende Methode prüft, ob ein Array mit "BEGIN" beginnt, mit "END" endet und mindestens ein Element dazwischen enthält:

static bool HasContent(string[] entries) =>
    entries is ["BEGIN", .. { Length: > 0 }, "END"];

Das äußere Muster erfordert zuerst die Markierung "BEGIN" bei Index 0 und "END" am letzten Index. Das Eigenschaftenmuster { Length: > 0 } fügt dann eine Anforderung für die Sequenz hinzu, die mit dem Segment übereinstimmt: Es muss mindestens ein Element enthalten. Zusammen beschreiben diese Anforderungen die vollständige Form. Das Muster testet die Werte der Elemente innerhalb des Slice nicht.

Verwenden Sie ein Slice-Unterpattern nur, wenn für den mittleren Teil selbst ein Test oder eine Erfassung erforderlich ist. Wenn nur Randelemente wichtig sind, ist ein einfaches .. einfacher.

Siehe auch