Přehled porovnávání vzorů

Tip

Tento článek je součástí části Základy pro vývojáře, kteří už znají aspoň jeden programovací jazyk a učí se jazyk C#. Pokud s programováním teprve začínáte, začněte nejprve kurzy Začínáme . Zkušení vývojáři jazyka C# můžou použít referenční informace o vzorech pro úplnou syntaxi a pravidla.

Pochází z jiného jazyka? Vzory v jazyce C# plní podobnou roli jako pattern matching v Javě a případy matchv Pythonu. Jazyk C# používá vzory ve is výrazech, switch příkazech a switch výrazech.

Porovnávání podle vzoru aplikuje vzor na výraz. Vzor je podmínka pro otestování vstupního výrazu. Vzorový vstup je tento výraz. Jazyk C# vyhodnotí vstupní výraz; výsledkem je vyhodnocená hodnota. Model testuje, zda má daná hodnota určitý typ, rovná se konkrétní hodnotě nebo má určitý tvar. Když se vzor shoduje, může váš kód používat informace získané testem, jako je konkrétnější typ nebo hodnota extrahovaná z objektu.

Vzor můžete použít ve třech kontextech:

  • Na pravé straně operátoru is.
  • V popisku case příkazu switch.
  • V rameni výrazu switch .

Vzory jsou často přehlednější než posloupnost porovnávacích výrazů, protože každá větev popisuje data, která zpracovává. Například následující metoda používá switch výraz k výběru zprávy o doručení:

static string GetDeliveryMessage(Delivery? delivery) =>
    delivery switch
    {
        null => "No delivery was scheduled.",
        ExpressDelivery express => $"Express package {express.TrackingCode}",
        StandardDelivery { Days: <= 2 } => "Standard delivery arriving soon",
        _ => "Standard delivery"
    };

Rekurzivní vzory mají vlastní vstupní výrazy. Ve vzoru StandardDelivery { Days: <= 2 } obdrží vnější vzor výraz delivery. Rekurzivní vzor <= 2 přijímá výraz vlastnosti Days ze spárovaného objektu StandardDelivery.

Výraz před switch je vstupním výrazem. Každá čára uvnitř složených závorek je rameno přepínače. Vzor se zobrazí před =>a výsledek se zobrazí za ním. Jazyk C# vyhodnotí vstupní výraz a pak vybere první rameno v pořadí textu, jehož vzor odpovídá a jehož volitelná when ochrana je true. Volitelný when kryt je další logická podmínka napsaná za vzorem. Předchozí příklad ukázal následující vzory:

  • null je konstantní vzor. Testuje, zda se delivery výraz vyhodnotí jako null.
  • ExpressDelivery express je vzor deklarace se dvěma částmi. ExpressDelivery je část typu testu. Testuje, zda vyhodnocená hodnota je nenulový objekt, jehož typ běhu je kompatibilní s ExpressDelivery. express je označení proměnné: deklaruje proměnnou s názvem express a přiřadí jí odpovídající ExpressDelivery objekt.
  • StandardDelivery { Days: <= 2 } začíná kontrolou typu. StandardDelivery testuje, zda vyhodnocená hodnota je nenulový objekt tohoto typu. Složené závorky obsahují vzor pro vlastnost. Days pojmenuje vlastnost, která se má zkontrolovat, takže Days výraz vlastnosti se stane vstupem rekurzivního vzoru. Část <= 2 je relační vzor, který testuje, zda je vyhodnocená hodnota menší nebo rovna 2.
  • _ (podtržítko) je vzor zahození. Odpovídá každé vyhodnocené hodnotě, včetně null. Protože předchozí větve už zpracovávají null, expresní zásilky a standardní zásilky doručené do dvou dnů, tato poslední větev zpracovává všechny zbývající hodnoty.

Ruka bez whenstráže je nehlídaná. Všechna ramena v prvním příkladu jsou nechráněná. Pokud dřívější větev bez podmínky odpovídá všem vyhodnocovaným hodnotám, kterým by mohla odpovídat pozdější větev, je pozdější větev zahrnuta. Pohlcený vzor je takový vzor, u něhož každá možná vstupní hodnota, která se s ním shoduje, už byla zachycena některou z předchozích větví příkazu switch. Nemůže se nikdy shodovat, takže kompilátor hlásí chybu. Větev zahození (_) musí být uvedena až jako poslední, protože odpovídá libovolnému vstupnímu výrazu. Strážené rameno nenasadí pozdější paži na základě svého vzoru samotného, protože stráž může být false.

Výraz switch je úplný, když jeho větve zpracovávají všechny možné hodnoty vstupního výrazu. První příklad je úplný, protože jeho poslední větev pro odhození zachytí vše, co předchozí větve nepokryjí. Kompilátor varuje, když detekuje potenciální vstupní hodnotu, kterou nezpracovává žádná větev. Kompilátor nemůže prokázat úplnost pro každou kombinaci vzorů, ale tato diagnostika vám pomůže psát správný kód pro porovnávání vzorů. Podrobná pravidla pro porovnávání, subsumpci a úplnost najdete v referenci vzorů.

Testování jedné podmínky pomocí is

Operátor is použijte, pokud potřebujete jeden logický test. Následující kód vyhodnocuje výraz delivery a použije deklarační vzor ExpressDelivery express. Typová část se shoduje, pokud je vyhodnocená hodnota nenulová a její typ za běhu je kompatibilní s ExpressDelivery. Když se vzor shoduje, označení jeho proměnné deklaruje express:

static void PrintTrackingCode(Delivery delivery)
{
    if (delivery is ExpressDelivery express)
    {
        Console.WriteLine($"Track express package {express.TrackingCode}");
    }
}

Kompilátor sleduje, jestli byla před čtením kódu přiřazena místní proměnná. Toto sledování se nazývá určité přiřazení. Uvnitř bloku if může být podmínka true jen tehdy, když vzor přiřadil odpovídající objekt proměnné express. Kompilátor proto ví, že express je tam určitě přiřazený. Kód může bezpečně používat jeho TrackingCode vlastnost. Nepotřebujete samostatné přetypování. Pokud potřebujete pouze test typu a nepotřebujete deklarovat proměnnou, použijte vzor typu, například delivery is ExpressDelivery.

Používejte is null nebo is not null pro kontroly null. Tyto vzory nevolají uživatelsky definovaný operátor == ani !=.

static void PrintPackageStatus(Delivery? delivery)
{
    if (delivery is null)
    {
        Console.WriteLine("No package is available.");
    }
    else
    {
        Console.WriteLine("A package is ready to track.");
    }
}

Další pokyny k zabezpečení proti hodnotě null naleznete v tématu referenční typy s možnou hodnotou null.

Volba mezi příkazem a výrazem

Vzory fungují u obou forem switch:

  • Použijte příkaz switch statement, pokud má každá větev provést jeden nebo více příkazů.
  • Použijte výraz switch, když má každá shoda vrátit hodnotu.

Následující příkaz switch hlásí aktualizaci doručení. Větev pro expresní doručení zapisuje dvě zprávy, takže sem příkaz přirozeně zapadá:

static void PrintDeliveryUpdate(Delivery? delivery)
{
    switch (delivery)
    {
        case null:
            Console.WriteLine("No delivery was scheduled.");
            break;
        case ExpressDelivery express:
            Console.WriteLine($"Express delivery {express.TrackingCode} is ready.");
            Console.WriteLine("Notify the priority desk.");
            break;
        case StandardDelivery standard:
            Console.WriteLine($"Standard delivery arrives in {standard.Days} days.");
            break;
        default:
            Console.WriteLine("Another delivery type is scheduled.");
            break;
    }
}

Každý case aplikuje vzor na výraz delivery. Odpovídající část může před tím, než break ukončí příkaz switch, spustit libovolný počet příkazů. Sekce default zpracovává vše, co neodpovídá žádnému z předchozích případů.

Následující switch výraz nahrazuje řetězec if / else if, který přiřazuje jeden výsledek:

static string GetStatusMessage(StandardDelivery delivery) =>
    delivery.Days switch
    {
        0 => "Delivered today",
        1 => "Arriving tomorrow",
        <= 3 => "Arriving soon",
        _ => "In transit"
    };

Výraz switch je výstižný, protože každá arm má stejný účel: vytvoří vrácenou hodnotu. Příkaz switch použijte, když větve provádějí akce a používají výraz switch při výpočtu jednoho výsledku.

Kategorie vzorů

Jazyk C# obsahuje vzory pro běžné druhy datových testů:

Kategorie vzorů Co testuje
Deklarace, konstanta a var vzory Typ běhu, konkrétní konstantní hodnota nebo libovolná hodnota, kterou chcete zachytit
Vzory typů Typ za běhu programu bez deklarace proměnné
Vlastnosti a poziční vzory Vlastnosti, pole nebo dekonstruované hodnoty
Relační a logické vzory Porovnání a kombinace, jako jsou and, or a not
Vzory seznamů Hodnoty a tvar seznamu nebo pole
Vzory a vyřazené položky Jakákoli zbývající hodnota nebo hodnota, kterou váš kód záměrně ignoruje

Články Základy propojené v tabulce poskytují prioritní pokrytí kategorií, které jsou aktuálně popsané v této části. Kompletní syntaxi a příklady pro všechny kategorie vzorů najdete v referenčních informacích k vzorům.

Viz také