Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Deklaration, konstant och
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 du inte har använt C#-mönster tidigare. Fullständiga språkregler finns i mönsterreferensen.
Ett mönster tillämpas på ett indatauttryck. C# utvärderar uttrycket, därefter testar eller fångar mönstret in det resulterande värdet. Deklaration, konstant och var mönster besvarar tre praktiska frågor:
- Deklarationsmönster: Har uttrycket genererat ett icke-null-värde av en kompatibel körningstyp? I så fall deklarerar du en variabel för det värdet.
- Konstant mönster: Gav uttrycket ett specifikt konstant värde?
-
varmönster: Vilket värde har uttrycket genererat? Fånga den utan att först testa dess typ eller värde.
Testa och avbilda en typ med ett deklarationsmönster
Ett deklarationsmönster består av en typ och en beteckning. Typen anger vilken körningstyp som ska testas. Beteckningen deklarerar variabeln som tar emot matchande värde.
Följande exempel tar emot ett object, så uttrycket kan ge många olika typer. Deklarationsmönstret låter den matchande grenen använda ett decimalvärde utan ett separat typtest och typomvandling:
static void PrintPrice(object value)
{
if (value is decimal amount)
{
Console.WriteLine($"Price: {amount:C}");
}
}
I value is decimal amount:
-
valueär indatauttrycket. C# utvärderar det först. -
decimalär den testade typen. Mönstret matchar när det utvärderade värdet inte är null och dess körningstyp är kompatibel meddecimal. -
amountär beteckningen. När mönstret matchar deklarerar detamountoch tilldelar det decimalvärdet.
Kompilatorn spårar om en lokal variabel tar emot ett värde innan koden läser den. Den här spårningen kallas för bestämd tilldelning. Inuti blocket if vet kompilatorn att amount har tilldelats eftersom blocket bara körs när mönstret matchar. Kompilatorn genererar ett fel om koden försöker komma åt amount utanför if blocket. Om value inte är ett decimal värde tilldelas inte variabeln amount till ett värde.
Välj ett deklarationsmönster när matchande gren måste använda resultatet som den testade typen. Den kombinerar test-, konverterings- och variabeldeklarationen, vilket undviker att upprepa uttrycket eller skriva en separat gjutning.
Du kan också använda deklarationsmönster när ett uttryck kan ge flera användbara typer:
static string FormatSensorValue(object reading) =>
reading switch
{
int count => $"Count: {count}",
double temperature => $"Temperature: {temperature:F1}°C",
string message => $"Message: {message}",
_ => "Unsupported reading"
};
Varje arm deklarerar en variabel av den matchade typen eftersom resultatet kräver den typens formateringsbeteende. Ett deklarationsmönster matchar endast när det utvärderade värdet inte är null och redan har en körtidstyp som är kompatibel med den testade typen via de konverteringar som är tillåtna för mönster.
null har ingen körningstidstyp som mönstret kan matcha. Mönstret kör inte heller användardefinierade konverteringsoperatorer: Det är ett typtest och en avbildning, inte en begäran om att konvertera värdet till en annan typ. Fullständiga kompatibilitetsregler finns i Deklarations- och typmönster.
Matcha ett specifikt värde med ett konstant mönster
Ett konstant mönster testar om ett uttryck skapar en viss konstant, till exempel ett tal, en sträng, boolesk, enummedlem, deklarerat const värde eller null.
Konstanta mönster passar ett växeluttryck när flera kända värden ger olika resultat:
static string GetCommandMessage(Command command) =>
command switch
{
Command.Start => "Starting",
Command.Stop => "Stopping",
Command.Pause => "Pausing",
_ => "Unknown command"
};
Command är en uppräkning, en typ som definierar en uppsättning namngivna konstanter.
Command.Start, Command.Stop, och Command.Pause är dess uppräkningsmedlemmar, så varje växelarm använder ett konstant mönster för att testa ett namngivet kommandovärde.
Välj det här formuläret när kommandot kan ha flera diskreta betydelser. Växlingsarmarna håller ihop värdena och deras resultat. För en enkel jämförelse av likhet är vanligtvis en if-sats som if (command == Command.Start) lättare att läsa.
Matchning med konstant mönster använder inbyggda regler för språkjämlikhet i stället för en användardefinierad == operator. Detaljerade regler för likhet och konvertering finns i referensen för konstanta mönster.
Det null konstanta mönstret är användbart för en tillförlitlig null-kontroll:
static bool HasText(string? text) => text is not null;
Välj is null eller is not null när du kontrollerar null-tillstånd. Dessa mönster anropar inte en användardefinierad likhetsoperator, inte ens när uttryckets typ överbelastas ==.
Samla in ett resultat för en vakt med ett var mönster
Ett var mönster matchar varje resultat, inklusive null, och deklarerar en variabel vars typ är indatauttryckets kompileringstidstyp. Det kan avbilda ett beräknat värde medan ett annat mönster redan matchar ett objekt:
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);
Deklarationsmönstret ExpressDelivery express avbildar först leveransobjektet som express. Metodanropet EstimateDays(express) är indatauttrycket för var mönstret. C# utvärderar metodanropet och var days samlar in den resulterande uppskattningen som days utan att testa dess typ eller värde. Uppskattningen kan vara en eller två dagar när vakten lyckas. Armresultatet behöver det registrerade värdet för att rapportera det faktiska antalet dagar.
En vanlig lokal variabel kan inte deklareras mellan ett switch-arm-mönster och dess when skydd. Om du anropar EstimateDays(express) igen i resultatet upprepas beräkningen. Välj det här var mönsterformuläret när koden redan matchar, och både skydd och resultat behöver ett beräknat mellanliggande värde.
Om du inte behöver det insamlade värdet använder du mönstret _ignorera i stället för att deklarera en variabel.