Mintaegyeztetés áttekintése

Tip

Ez a cikk az Alapismeretek szakasz része azon fejlesztők számára, akik már legalább egy programozási nyelvet ismernek, és c#-t tanulnak. Ha még csak most ismerkedik a programozással, először az Első lépések oktatóanyagokkal kezdje. A tapasztalt C#-fejlesztők használhatják a mintákra vonatkozó hivatkozást a teljes szintaxishoz és szabályokhoz.

Más nyelvről jön? A C#-minták Java mintaegyezéséhez és Python esetéhez match hasonló szerepkört szolgálnak ki. A C# mintákat használ a switch kifejezésekben, a switch utasításokban és a is kifejezésekben.

A mintaegyezés mintázatot alkalmaz egy kifejezésre. A minta a bemeneti kifejezés tesztelésének feltétele. A mintabemenet az a kifejezés. A C# kiértékeli a bemeneti kifejezést; az eredmény a kiértékelt érték. A minta azt ellenőrzi, hogy az értéknek van-e egy adott típusa, egy adott értéknek felel meg, vagy egy adott alakzattal rendelkezik. Ha egy minta egyezik, a kód felhasználhatja a teszt által tanult információkat, például egy konkrétabb típust vagy egy objektumból kinyert értéket.

A mintát három környezetben használhatja:

  • A(z) is operátor jobb oldalán.
  • case Egy utasítás címkéjébenswitch.
  • Egy switch kifejezési ágban.

A minták egy kiértékelt bemenetet tesztelnek típusok, állandók vagy beágyazott mintákat tartalmazó alakzatok alapján. A logikai feltétel két egymástól függetlenül kiértékelt kifejezést is összehasonlíthat, amelyek értékei nem állandók. Ha bármelyik űrlap ki tudja fejezni ugyanazt a tesztet, válassza ki az könnyebben olvasható űrlapot.

A következő metódus például kifejezéssel switch választ ki egy kézbesítési üzenetet:

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

A tulajdonságminták tartalmazhatnak külső típustesztet és beágyazott mintákat, de egyik sem szükséges minden tulajdonságmintában. Ebben StandardDelivery { Days: <= 2 }a esetben a külső minta megkapja a delivery kifejezést, és teszteli annak típusát. A Days tulajdonságkifejezés ezután a beágyazott relációs minta <= 2bemenetévé válik.

Az előző switch kifejezés a bemeneti kifejezés. A kapcsos zárójeleken belüli minden sor egy kapcsolóág. A minta a => előtt jelenik meg, az eredmény pedig utána. A C# kiértékeli a bemeneti kifejezést, majd kiválasztja az első kart szöveges sorrendben, amelynek mintája megegyezik, és amelynek az opcionális when védője .true Az opcionális when védő egy további logikai feltétel, amelyet a minta után írtak. Az előző példa a következő mintákat mutatta:

  • null egy konstans minta. Azt ellenőrzi, hogy a delivery kifejezés értéke null-e.
  • ExpressDelivery express két részből álló deklarációs minta . ExpressDelivery a típustesztelési rész. Ellenőrzi, hogy a kiértékelt érték nem null értékű objektum-e, amelynek futásidejű típusa kompatibilis-e.ExpressDelivery express a változó megjelölése: deklarál egy elnevezett express változót, és hozzárendeli hozzá a megfeleltethető objektumot ExpressDelivery .
  • StandardDelivery { Days: <= 2 } típusteszttel kezdődik. StandardDelivery ellenőrzi, hogy a kiértékelt érték nem null értékű-e. A kapcsos zárójelek tulajdonságmintát tartalmaznak. Days nevet ad a vizsgálandó tulajdonságnak, így a Days tulajdonságkifejezés lesz a rekurzív minta bemenete. A <= 2 rész egy relációs minta, amely ellenőrzi, hogy a kiértékelt érték kisebb vagy egyenlő-e 2.
  • A _ (aláhúzás) az eldobási minta. Minden kiértékelt értéknek megfelel, beleértve a null. Mivel a korábbi ágak már kezelik a null expressz kézbesítéseket és a két napon belül érkező standard kézbesítéseket, ez az utolsó ág az összes többi értéket kezeli.

Az őr nélküli when karok védtelenek. Az első példában szereplő összes kar őrzetlen. Ha egy korábbi nem őrzött kar megfelel minden kiértékelt értéknek, amelyet egy későbbi kar megfeleltethet, a későbbi kar részösszegzett lesz. Az alösszegzett minta olyan, amelyben minden lehetséges, egyező bemeneti értéket egy korábbi kapcsolókar már egyeztetett. Ez soha nem egyezhet, ezért a fordító hibát jelez. Az eldobó ágnak (_) utolsóként kell szerepelnie, mert minden bemeneti kifejezésre illeszkedik. Egy őrfeltétellel ellátott kar önmagában a mintája alapján nem foglal magában egy későbbi kart, mert az őrfeltétel lehet false.

Egy kapcsolókifejezés akkor kimerítő, ha az ágai minden lehetséges bemeneti kifejezést kezelnek. Az első példa teljes körű, mert a végső eldobási ág minden olyan esetet kezel, amelyre a korábbi ágak nem illenek. A fordító figyelmeztet, ha olyan lehetséges bemeneti értéket észlel, amelyet egyik ág sem kezel. A fordító nem tudja bizonyítani a minták minden kombinációjának teljességét, de ez a diagnosztika segít a helyes mintaegyező kód megírásában. A részletes egyeztetési, részkiosztási és teljességi szabályokért tekintse meg a mintákra vonatkozó hivatkozást.

Teszteljen egy feltételt a(z) is használatával.

Használja az operátort is , ha egy logikai tesztre van szüksége. Az alábbi kód kiértékeli a delivery kifejezést, és alkalmazza a deklarációs mintát ExpressDelivery express. A típusrész akkor egyezik, ha a kiértékelt érték nem null, és a futásidejű típusa kompatibilis a(z) ExpressDelivery típussal. Ha a minta egyezik, a változó megjelölése a következőt deklarálja express:

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

A fordító nyomon követi, hogy egy helyi változó van-e hozzárendelve, mielőtt a kód felolvassa. Ezt a nyomkövetést határozott hozzárendelésnek nevezzük. A if blokkon belül a feltétel csak akkor lehet true, ha a minta az egyező objektumot a express változóhoz rendelte hozzá. A fordító ezért tudja, hogy express az biztosan oda van rendelve. A kód biztonságosan használhatja a tulajdonságát TrackingCode . Nincs szükség külön szereposztásra. Ha csak a típustesztre van szüksége, és nem kell változót deklarálnia, használjon típusmintát, például delivery is ExpressDelivery.

Nullérték-ellenőrzéshez használja a(z) is null vagy is not null elemet. Ezek a minták nem hívnak meg felhasználó által definiált == vagy != operátort.

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

A nullbiztossággal kapcsolatos további útmutatásért lásd a null értéket engedélyező referenciatípusokat.

Válasszon egy utasítás és egy kifejezés között

A minták a következők mindkét formájával switchműködnek:

  • Akkor használjon egy switch utasítást, ha minden egyezéshez egy vagy több utasítást kell végrehajtani.
  • Akkor használjon kifejezést switch , ha minden egyezésnek értéket kell létrehoznia.

A következő switch utasítás egy kézbesítési állapotfrissítésről ad tájékoztatást. Az expressz kézbesítési ág két üzenetet ír ki, így egy utasítás természetesen illik bele:

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

Mindegyik case egy mintát alkalmaz a delivery kifejezésre. Az egyező szakasz tetszőleges számú utasítást futtathat, mielőtt break kilép a kapcsolóból. Az default szakasz mindent kezel, amire a korábbi esetek nem illeszkednek.

A következő kapcsolókifejezés egy if / else if olyan láncot vált fel, amely egy eredményt rendel hozzá:

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

A kapcsolókifejezések tömörek, mert minden karnak ugyanaz a célja: a visszaadott érték előállítása. Ha az ágak műveleteket végeznek, kapcsolóutasítást használjon, és használjon kapcsolókifejezést, amikor az ágak kiszámítanak egy eredményt.

Minták kategóriái

A C# az adattesztek gyakori típusainak mintáit tartalmazza:

Minta kategória Mit tesztel?
Deklaráció, állandó és var minták Futásidejű típus, adott állandó érték vagy bármely rögzíteni kívánt érték
Típusminták Egy futásidejű típus változó deklarálása nélkül
Tulajdonság- és pozícióminták Tulajdonságok, mezők vagy dekonstruált értékek
Relációs, logikai és zárójeles minták Összehasonlítások és kombinációk, például and: , orés not
Listák és szeletelési minták Támogatott sorozat értékei és alakja
Minták és eldobások elvetése Bármely megmaradt érték, vagy egy érték, amelyet a kód szándékosan figyelmen kívül hagy

A csatolt alapismeretek cikkek ismertetik, hogy mikor érdemes választani az egyes kategóriákat. A teljes szintaxisért és példákért tekintse meg a mintákra vonatkozó hivatkozást.

Lásd még