List- och segmentmönster

Tip

Den här artikeln är en del av avsnittet Grunderna för utvecklare som redan känner till minst ett programmeringsspråk och lär sig C#. Börja med mönstermatchningsöversikten om mönster är nya för dig. Fullständiga typ- och språkregler som stöds finns i listmönster i språkreferensen.

En sekvenss form är den uppsättning observerbara egenskaper som ett mönster kräver. Dessa egenskaper kan omfatta antalet element, krav som skrivits för varje element eller för en sekvens av element som helhet och markörvärden vid specifika index. En form kan till exempel kräva exakt två element med "Name" vid index 0, eller så kan den kräva en första markör, en sista markör och en icke-tom sekvens mellan dem.

Ett listmönster beskriver en form genom att kombinera ett krav för antal element med kapslade mönster vid ordnade positioner. Den testar endast kraven som skrivits i mönstret: Ett element underordnat testar dess motsvarande element, medan ett segmentmönster kan tillåta eller testa en sekvens med annars omatchade element. Du kan använda dessa delar för att matcha ett exakt antal och markörvärden, samla in värden vid fasta positioner, tillåta en oöverträffad mitten eller tillämpa ett kapslat mönster på mitten.

Välj ett listmönster när indatans kompileringstidstyp har egenskapen Length eller Count och indexerad elementåtkomst, som hämtar ett element utifrån dess position, som i input[index]. Matriser, List<T>, strängar och intervall är vanliga exempel. Kompilatorn avgör berättigande från variabelns deklarerade kompileringstidstyp eftersom den måste matcha de nödvändiga medlemmarna innan programmet körs. Gränssnittet IEnumerable<T> i sig tillhandahåller uppräkning i stället för dessa medlemmar, även när körningsobjektet är en indexerbar samling.

Listmönster använder en längd eller antal och indexerad elementåtkomst i stället för uppräkning. För vanliga inbyggda typer kan matchning endast kontrollera de positioner som namnges av mönstret i stället för att iterera genom varje element. Kostnaden för dessa åtgärder beror på indatatypen. Iterering av en lång samling kan ta tid, så använd en loop eller LINQ när beslutet kräver att du undersöker ett godtyckligt antal element i stället för specifika positioner.

Matcha mot en exakt form

Följande metod identifierar en rubrik med två kolumner:

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

Uttrycket columns är mönsterindata. ["Name", "Score"] innehåller två konstanta mönster. Ett exakt listmönster utelämnar ett segmentmönster, kräver exakt två element och tillämpar varje kapslat mönster på elementet i samma index. Det här mönstret beskriver en form med ett exakt antal och två markörvärden: "Name" vid index 0 och "Score" vid index 1. Kapslade elementmönster är valfria: Det tomma listmönstret [] beskriver och matchar en sekvens utan element.

Välj ett listmönster när formen kombinerar ett elementantal med krav på ordnade positioner. Om bara antalet element är viktigt, anger ett Length egenskapsmönster Count , till exempel items is { Count: 0 }, avsikten mer direkt.

Använd ett discard för att matcha alla elementvärden

Följande metod läser vinnaren och den som kom på tredje plats från en slutordning med tre namn:

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

Mönstren var winner och var thirdPlace deklarerar var och en en variabel. När listmönstret matchar tilldelar C# det matchade elementvärdet vid den positionen till motsvarande variabel, så att resultatet kan använda winner och thirdPlace. Mönstret _ accepterar det andra elementet och ignorerar dess värde. Den här formen kräver exakt tre element och ger den första och tredje positionen specifik betydelse, men den kräver inte särskilda värden på någon position.

Välj det här formuläret när fasta positioner har en stabil betydelse. Använd en loop eller LINQ när du behöver inspektera ett godtyckligt antal element, transformera en sekvens, söka i den eller utföra aggregering.

Tillåt återstående element med ett segmentmönster

I det här förenklade exemplet kan en kommandorad börja med --verbose och innehålla andra argument och antas sluta med indatafilens namn. Följande metod identifierar former med ett filnamn i den sista positionen och samlar in värdet:

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

Sektormönstret.. tillåter noll eller fler återstående element mellan det första och sista elementmönstret. Ett listmönster kan innehålla högst ett segmentmönster. Den första växlingsarmen beskriver en form med minst två element: markören "--verbose" vid index 0, ett filnamn i den sista positionen och valfritt antal omatchade argument mellan dem. Den fristående slicen testar inte de mellersta argumenten. Den andra armen accepterar vilket icke-tomt mönster som helst och fångar dess sista element, medan det tomma mönstret matchar en sekvens utan element.

Ett segment kan visas i början, mitten eller slutet av ett listmönster. Använd den när en sekvens med variabel längd är en del av formen, men endast de omgivande positionerna behöver elementtester. Använd vanlig iteration när varje element behöver bearbetas.

Tillämpa ett mönster på ett segment

Du kan använda ett annat mönster för den del som matchas av ... Följande metod testar om en matris börjar med "BEGIN", slutar med "END"och har minst ett element mellan sig:

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

Det yttre mönstret kräver först markören "BEGIN" vid index 0 och "END" vid det sista indexet. Egenskapsmönstret { Length: > 0 } lägger sedan till ett krav för sekvensen som matchas av sektorn: Den måste innehålla minst ett element. Tillsammans beskriver dessa krav hela formen. Mönstret testar inte elementens värden i slicen.

Använd endast ett segmentundermönster när själva mittendelen behöver ett test eller en avbildning. Om endast gränselement spelar roll är det enklare att använda klartext .. .

Se även