Declaratie-, constante- en var-patronen

Tip

Dit artikel maakt deel uit van de sectie Grondbeginselen voor ontwikkelaars die al ten minste één programmeertaal kennen en C# leren. Begin met het overzicht van patroonkoppeling als u nog geen C#-patronen hebt gebruikt. Zie de referentie voor patronen voor volledige taalregels.

Een patroon wordt toegepast op een invoerexpressie. C# evalueert de expressie en vervolgens de patroontests of legt de resulterende waarde vast. Declaratie, constante en var patronen beantwoorden drie praktische vragen:

  • Declaratiepatroon: Heeft de expressie een niet-null-waarde van een compatibel runtimetype geproduceerd? Zo ja, declareer dan een variabele voor die waarde.
  • Constant patroon: Heeft de expressie één specifieke constante waarde geproduceerd?
  • var patroon: Welke waarde heeft de expressie geproduceerd? Leg het vast zonder eerst het type of de waarde ervan te testen.

Een type testen en vastleggen met een declaratiepatroon

Een declaratiepatroon bestaat uit een type en een aanduiding. Het type geeft aan welk runtimetype moet worden getest. De aanduiding declareert de variabele die de overeenkomende waarde ontvangt.

In het volgende voorbeeld krijgt de expressie een object, waardoor deze veel verschillende typen kan opleveren. Met het declaratiepatroon kan de matchende tak een decimale waarde gebruiken zonder een afzonderlijke typetest en typeconversie:

static void PrintPrice(object value)
{
    if (value is decimal amount)
    {
        Console.WriteLine($"Price: {amount:C}");
    }
}

In value is decimal amount:

  • value is de invoerexpressie. C# evalueert het eerst.
  • decimal is het geteste type. Het patroon komt overeen wanneer de geëvalueerde waarde niet null is en het runtimetype compatibel is met decimal.
  • amount is de aanduiding. Wanneer het patroon overeenkomt, declareert het amount en wijst het de decimale waarde eraan toe.

De compiler houdt bij of een lokale variabele een waarde ontvangt voordat uw code deze leest. Deze tracering wordt een definitieve toewijzing genoemd. Binnen het if blok weet de compiler dat amount is toegewezen omdat het blok alleen wordt uitgevoerd wanneer het patroon overeenkomt. De compiler produceert een fout als uw code buiten het if-blok toegang probeert te krijgen tot amount. Als value geen waarde van decimal is, krijgt de variabele amount geen waarde toegewezen.

Kies een declaratiepatroon wanneer de overeenkomende vertakking het resultaat moet gebruiken als het geteste type. Het combineert de test, de conversie en de declaratie van de variabele, zodat je de expressie niet hoeft te herhalen of een aparte cast hoeft te schrijven.

U kunt ook declaratiepatronen gebruiken wanneer één expressie verschillende nuttige typen kan produceren:

static string FormatSensorValue(object reading) =>
    reading switch
    {
        int count => $"Count: {count}",
        double temperature => $"Temperature: {temperature:F1}°C",
        string message => $"Message: {message}",
        _ => "Unsupported reading"
    };

Elke arm declareert een variabele van het overeenkomende type omdat het resultaat het opmaakgedrag van dat type nodig heeft. Een declaratiepatroon komt alleen overeen wanneer de geëvalueerde waarde niet null is en al een runtimetype heeft dat compatibel is met het geteste type via de conversies die zijn toegestaan voor patronen. null heeft geen runtime-type waarmee het patroon kan overeenkomen. Het patroon voert ook geen door de gebruiker gedefinieerde conversieoperators uit: het is een typetest en vastleggen, geen aanvraag om de waarde te converteren naar een ander type. Zie Declaratie- en typepatronen voor de volledige compatibiliteitsregels.

Een specifieke waarde vergelijken met een constant patroon

Een constant patroon test of een expressie een bepaalde constante produceert, zoals een getal, tekenreeks, Booleaanse waarde, enumlid, gedeclareerde const waarde of null.

Constante patronen passen bij een schakelexpressie wanneer verschillende bekende waarden elk een ander resultaat opleveren:

static string GetCommandMessage(Command command) =>
    command switch
    {
        Command.Start => "Starting",
        Command.Stop => "Stopping",
        Command.Pause => "Pausing",
        _ => "Unknown command"
    };

Command is een enum, een type dat een set benoemde constanten definieert. Command.Start, Command.Stop, en Command.Pause zijn de leden van de enum, dus elke switch-arm gebruikt een constant patroon om één benoemde opdrachtswaarde te testen.

Kies dit formulier wanneer de opdracht verschillende discrete betekenissen kan hebben. De schakelarmen houden de waarden en hun resultaten bij elkaar. Voor een eenvoudige gelijkheidsvergelijking is een if verklaring zoals if (command == Command.Start) meestal gemakkelijker te lezen.

Constant patroonkoppeling maakt gebruik van ingebouwde regels voor taalgelijkheid in plaats van een door de gebruiker gedefinieerde == operator. Zie de referentie voor constant patroon voor gedetailleerde gelijkheids- en conversieregels.

Het null constante patroon is handig voor een betrouwbare null-controle:

static bool HasText(string? text) => text is not null;

Kies is null of is not null wanneer u de null-status controleert. Met deze patronen wordt geen door de gebruiker gedefinieerde gelijkheidsoperator aangeroepen, zelfs niet wanneer het type van de expressie overbelast raakt ==.

Een resultaat vastleggen voor een bewaker met een var patroon

Een var patroon komt overeen met elk resultaat, inclusief null, en declareert een variabele waarvan het type het compileertijdtype van de invoerexpressie is. Er kan een berekende waarde worden vastgelegd terwijl een ander patroon al overeenkomt met een object:

static string GetDeliveryMessage(object delivery) =>
    delivery switch
    {
        ExpressDelivery express
            when EstimateDays(express) is var days && days <= 2
                => $"Arrives in {days} day{(days == 1 ? "" : "s")}",
        ExpressDelivery => "Express delivery for your location takes more than two days",
        _ => "Standard delivery"
    };

static int EstimateDays(ExpressDelivery delivery) =>
    delivery.MilesAway <= 500 ? 1 :
    delivery.MilesAway <= 1_000 ? 2 : 3;

record ExpressDelivery(int MilesAway);

Het declaratiepatroon ExpressDelivery express legt eerst het leveringsobject vast als express. De methode-aanroep EstimateDays(express) is de invoerexpressie voor het var patroon. C# evalueert die methode-aanroep en var days legt de resulterende schatting days vast, zonder het type of de waarde ervan te testen. De schatting kan één of twee dagen duren wanneer de bewaker slaagt. Het arm-resultaat heeft de vastgelegde waarde nodig om het werkelijke aantal dagen te rapporteren.

Een gewone lokale variabele kan niet worden gedeclareerd tussen een schakelarmpatroon en de when bijbehorende bewaker. Als u EstimateDays(express) opnieuw aanroept in het resultaat, wordt de berekening herhaald. Kies dit var patroonformulier wanneer de code al overeenkomt, en zowel de guard als het resultaat hebben een berekende tussenliggende waarde nodig.

Als u de vastgelegde waarde niet nodig hebt, gebruikt u het verwijderingspatroon _ in plaats van een variabele te declareren.

Zie ook