.NET-HILFE

C# Pattern-Matching-Ausdrücke (So funktioniert es für Entwickler)

Veröffentlicht 26. März 2024
Teilen Sie:

Einführung

Der Mustervergleich in C# ist eine leistungsstarke Funktion, die in C# 7.0 eingeführt und in den nachfolgenden Versionen erweitert wurde. Es ermöglicht Entwicklern, prägnanteren und aussagekräftigeren Code zu schreiben, wenn sie mit bedingten Anweisungen, Typüberprüfung und Dekonstruktion von Objekten arbeiten.

Mustervergleichsausdrücke bieten eine flexible und intuitive Möglichkeit, Werte mit Mustern abzugleichen und entsprechende Codeblöcke auszuführen. In diesem Artikel werden wir die Feinheiten von Mustervergleichsausdrücken in C# erkunden, einschließlich Syntax, Anwendungsfälle und Codebeispiele. Am Ende des Artikels werden wir auch ein wenig über IronPDF von Iron Software um ein PDF-Dokument in C#-Anwendungen zu erzeugen.

Vorteile des Mustervergleichs in C##

Der Musterabgleich in C#-Code bietet eine Fülle von Vorteilen:

  • Verbesserte Lesbarkeit: Der Musterabgleich vereinfacht komplexe bedingte Logik, so dass Ihr Code sowohl für Sie als auch für andere Entwickler leichter zu verstehen und nachzuvollziehen ist.
  • Reduzierung der Codezeilen: Durch die Zusammenfassung komplizierter bedingter Anweisungen zu prägnanten Mustern trägt der Musterabgleich zur Straffung Ihrer Codebasis bei, was zu weniger Codezeilen und einer prägnanteren Implementierung führt.
  • Verbesserte Wartbarkeit: Die Klarheit, die der Musterabgleich bietet, erleichtert die Wartung und das Debugging des Codes. Mit klar abgegrenzten Mustern wird es einfacher, bestimmte Logikblöcke zu identifizieren und bei Bedarf zu ändern, ohne den Rest der Codebasis zu beeinträchtigen.
  • Aussagekräftigere Algorithmen: Der Musterabgleich ermöglicht es Entwicklern, Algorithmen auf natürlichere und intuitivere Weise auszudrücken. Durch den Abgleich von Codestrukturen mit Problemlösungsparadigmen erleichtert der Musterabgleich die Erstellung von Algorithmen, die ihren konzeptionellen Modellen sehr ähnlich sind.

Arten von Mustervergleichen in C#;

Der Mustervergleich wird durch die folgenden Ausdrücke unterstützt:

  • ist Ausdruck
  • switch-Anweisungen
  • schaltausdrücke

    Die folgenden Muster können verwendet werden, um mit den Konstrukten übereinzustimmen:

Deklarations- und Typmuster

Deklarations- und Typmuster sind in C# unverzichtbare Werkzeuge, um die Kompatibilität von Laufzeitausdrücken mit vorgegebenen Typen zu prüfen. Mit Deklarationsmustern können Sie sowohl die Kompatibilität prüfen als auch gleichzeitig eine neue lokale Variable deklarieren. Betrachten Sie das folgende Beispiel:

object greeting = "Iron Software is Awesome!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: Iron Software is Awesome!
}
object greeting = "Iron Software is Awesome!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: Iron Software is Awesome!
}
Dim greeting As Object = "Iron Software is Awesome!"
Dim tempVar As Boolean = TypeOf greeting Is String
Dim message As String = If(tempVar, DirectCast(greeting, String), Nothing)
If tempVar Then
	Console.WriteLine(message.ToLower()) ' output: Iron Software is Awesome!
End If
VB   C#

Hier stellt das Deklarationsmuster sicher, dass der Ausdruck greeting, wenn er mit dem Typ string übereinstimmt, der Variablen message zugewiesen wird, was nachfolgende Operationen ermöglicht.

Wenn eine der folgenden Bedingungen zutrifft, ist das Deklarationsmuster gültig:

  • Der Laufzeittyp des Ausdrucks ist T.
  • Der Laufzeittyp des Ausdrucks leitet sich von T ab, implementiert die Schnittstelle T oder kann implizit in T konvertiert werden.
  • Der Laufzeittyp des Ausdrucks ist ein löschbarer Werttyp mit dem zugrunde liegenden Typ T.
  • Es gibt eine Boxing- oder Unboxing-Konvertierung vom Laufzeittyp des Ausdrucks zum Typ T.

    Betrachten Sie das folgende Beispiel, das die oben genannten Bedingungen veranschaulicht:

int? nullableX = 8;
int y = 45;
object boxedy = y;
if (nullableX is int a && boxedy is int b)
{
    Console.WriteLine(a + b);  // output: 53
}
int? nullableX = 8;
int y = 45;
object boxedy = y;
if (nullableX is int a && boxedy is int b)
{
    Console.WriteLine(a + b);  // output: 53
}
Dim nullableX? As Integer = 8
Dim y As Integer = 45
Dim boxedy As Object = y
Dim tempVar As Boolean = TypeOf boxedy Is Integer
Dim b As Integer = If(tempVar, DirectCast(boxedy, Integer), Nothing)
Dim tempVar2 As Boolean = TypeOf nullableX Is Integer
Dim a As Integer = If(tempVar2, CInt(nullableX), Nothing)
If tempVar2 AndAlso tempVar Then
	Console.WriteLine(a + b) ' output: 53
End If
VB   C#

Hier passt nullableX auf das Muster, da es sich um einen nullbaren Werttyp mit dem zugrundeliegenden Typ int handelt, und boxedy passt, da es zu int unboxed werden kann.

Wenn Sie nur den Typ eines Ausdrucks überprüfen müssen, ohne eine neue Variable zu deklarieren, können Sie die Funktion discard _ verwenden, wie im folgenden Beispiel zu sehen:

public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    bus _ => 4.00m,
    motor _ => 8.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    bus _ => 4.00m,
    motor _ => 8.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
'{
'	bus _ => 4.00m,
'	motor _ => 8.50m,
'	null => throw new ArgumentNullException(nameof(vehicle)),
'	_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
'};
VB   C#

In diesem Ausschnitt dient das _ als Platzhalter für ein beliebiges typgleiches Fahrzeug.

Sowohl Deklarations- als auch Typmuster stellen sicher, dass Ausdrücke vor dem Mustervergleich nicht null sind. Sie können auf Nicht-Null prüfen, indem Sie ein negiertes Null-Konstantenmuster verwenden, wie unten dargestellt:

if (inputVal is not null)
{
    // ...
}
if (inputVal is not null)
{
    // ...
}
If inputVal IsNot Nothing Then
	' ...
End If
VB   C#

Diese Negation stellt sicher, dass die Eingabe nicht Null ist, bevor weitere Operationen durchgeführt werden.

Durch die Nutzung von Deklarations- und Typmustern in Ihrem C#-Code können Sie die Lesbarkeit verbessern, Codezeilen reduzieren und Algorithmen effektiver ausdrücken. Diese Muster bieten eine prägnante und ausdrucksstarke Methode zur Handhabung typbasierter Logik und verbessern die Wartbarkeit Ihrer Codebasis.

Konstantes Muster

Konstante Muster dienen dazu, zu überprüfen, ob ein Ausdrucksergebnis mit einem bestimmten konstanten Wert übereinstimmt. Betrachten Sie das folgende Beispiel:

public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
    1 => 2.0m,
    2 => 10.0m,
    3 => 25.0m,
    4 => 60.0m,
    0 => 0.0m,
    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};
public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
    1 => 2.0m,
    2 => 10.0m,
    3 => 25.0m,
    4 => 60.0m,
    0 => 0.0m,
    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};
Dim tempVar As Decimal
Select Case visitorCount
	Case 1
		tempVar = 2.0D
	Case 2
		tempVar = 10.0D
	Case 3
		tempVar = 25.0D
	Case 4
		tempVar = 60.0D
	Case 0
		tempVar = 0.0D
	Case Else
'INSTANT VB TODO TASK: Throw expressions are not converted by Instant VB:
'ORIGINAL LINE: tempVar = throw new ArgumentException(string.Format("Not supported number of visitors: {0}", visitorCount), nameof(visitorCount));
		tempVar = throw New ArgumentException($"Not supported number of visitors: {visitorCount}", NameOf(visitorCount))
End Select
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'public static decimal GetGroupTicketPrice(int visitorCount)
'{
'	Return tempVar;
'}
VB   C#

Hier prüfen die Konstantenmuster, ob visitorCount mit einem der angegebenen Konstantenwerte übereinstimmt und geben entsprechende Ticketpreise zurück.

In einem Konstantenmuster können Sie verschiedene Arten von konstanten Ausdrücken verwenden, wie z. B.:

  1. Numerische Ganzzahl- oder Gleitkomma-Literale.

  2. Zeichen.

  3. String-Literale.

  4. Boolesche Werte (richtig oder falsch).

  5. Enum-Werte.

  6. Der Name eines deklarierten const-Feldes oder eines Local.

  7. null.

    Ein Ausdruck vom Typ Span oder ReadOnlySpan kann mit konstanten Zeichenketten übereinstimmen.

    Um auf Null zu prüfen, verwenden Sie ein konstantes Muster wie dieses:

if (inputVal is null)
{
    return;
}
if (inputVal is null)
{
    return;
}
If inputVal Is Nothing Then
	Return
End If
VB   C#

Hier stellt das Muster sicher, dass die Eingabe Null ist, bevor weitere Operationen durchgeführt werden.

Sie können auch ein negiertes Null-Konstantenmuster verwenden, um Nicht-Null-Werte zu ermitteln:

if (inputVal is not null)
{
    // ...
}
if (inputVal is not null)
{
    // ...
}
If inputVal IsNot Nothing Then
	' ...
End If
VB   C#

Dieses Muster verifiziert, dass die Eingabe nicht null ist, so dass nachfolgende Operationen sicher durchgeführt werden können.

Durch die Einbindung von Konstantenmustern in Ihren C#-Code können Sie Szenarien, in denen bestimmte Konstantenwerte abgeglichen werden müssen, effektiv handhaben und so die Klarheit und Wartbarkeit des Codes verbessern.

Beziehungsmuster

Relationale Muster bieten eine Möglichkeit, Ausdrucksergebnisse mit Konstanten zu vergleichen. Betrachten Sie das folgende Beispiel:

Console.WriteLine(Classify(20));  // output: Too high
Console.WriteLine(Classify(double.NaN));  // output: Unknown
Console.WriteLine(Classify(4));  // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};
Console.WriteLine(Classify(20));  // output: Too high
Console.WriteLine(Classify(double.NaN));  // output: Unknown
Console.WriteLine(Classify(4));  // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};
Console.WriteLine(Classify(20)) ' output: Too high
Console.WriteLine(Classify(Double.NaN)) ' output: Unknown
Console.WriteLine(Classify(4)) ' output: Acceptable
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string Classify(double measurement) => measurement switch
'{
'	< -4.0 => "Too low",
'	> 10.0 => "Too high",
'	double.NaN => "Unknown",
'	_ => "Acceptable",
'};
VB   C#

In diesem Fall vergleichen die relationalen Muster die Messung mit bestimmten Schwellenwerten, um ihre Klassifizierung zu bestimmen.

Der rechte Teil eines relationalen Musters muss ein konstanter Ausdruck sein, der vom Typ Ganzzahl, Gleitkomma, Char oder "enum" sein kann. Auf der linken Seite können die Operatoren <, >, <=, oder >= verwendet werden.

Um ein Ausdrucksergebnis innerhalb eines bestimmten Bereichs zu finden, verwenden Sie einen Konjunktiv und ein Muster, wie unten dargestellt:

Console.WriteLine(GetCalendarSeason(new DateTime(2024, 3, 12)));  // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 7, 12)));  // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 2, 12)));  // output: winter
static string GetCalendarSeason(DateTime date) => date.Month switch
{
    >= 3 and < 6 => "spring",
    >= 6 and < 9 => "summer",
    >= 9 and < 12 => "autumn",
    12 or (>= 1 and < 3) => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 3, 12)));  // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 7, 12)));  // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 2, 12)));  // output: winter
static string GetCalendarSeason(DateTime date) => date.Month switch
{
    >= 3 and < 6 => "spring",
    >= 6 and < 9 => "summer",
    >= 9 and < 12 => "autumn",
    12 or (>= 1 and < 3) => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
Console.WriteLine(GetCalendarSeason(New DateTime(2024, 3, 12))) ' output: spring
Console.WriteLine(GetCalendarSeason(New DateTime(2024, 7, 12))) ' output: summer
Console.WriteLine(GetCalendarSeason(New DateTime(2024, 2, 12))) ' output: winter
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string GetCalendarSeason(DateTime date) => date.Month switch
'{
'	>= 3 and < 6 => "spring",
'	>= 6 and < 9 => "summer",
'	>= 9 and < 12 => "autumn",
'	12 or (>= 1 and < 3) => "winter",
'	_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
'};
VB   C#

In diesem Auszug wird beschrieben, wie das konjunktive "und"-Muster verwendet wird, um die Kalenderjahreszeit anhand der Monate zu bestimmen, die in bestimmte Bereiche fallen. Außerdem wird erwähnt, dass relationale Muster ein prägnantes und aussagekräftiges Mittel zum Vergleich von Ausdrucksergebnissen mit Konstanten darstellen und so die Klarheit und Wartbarkeit des Codes verbessern.

Muster verwerfen

Das Verwerfungsmuster, bezeichnet mit _, dient der Übereinstimmung mit jedem Ausdruck, einschließlich Null. Nehmen Sie das folgende Beispiel:

Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0
Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0
static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
    DayOfWeek.Monday => 0.5m,
    DayOfWeek.Tuesday => 12.5m,
    DayOfWeek.Wednesday => 7.5m,
    DayOfWeek.Thursday => 12.5m,
    DayOfWeek.Friday => 5.0m,
    DayOfWeek.Saturday => 2.5m,
    DayOfWeek.Sunday => 2.0m,
    _ => 0.0m,
};
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0
Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0
static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
    DayOfWeek.Monday => 0.5m,
    DayOfWeek.Tuesday => 12.5m,
    DayOfWeek.Wednesday => 7.5m,
    DayOfWeek.Thursday => 12.5m,
    DayOfWeek.Friday => 5.0m,
    DayOfWeek.Saturday => 2.5m,
    DayOfWeek.Sunday => 2.0m,
    _ => 0.0m,
};
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday)) ' output: 5.0
Console.WriteLine(GetDiscountInPercent(Nothing)) ' output: 0.0
Console.WriteLine(GetDiscountInPercent(CType(10, DayOfWeek))) ' output: 0.0
Dim tempVar As Decimal
Select Case dayOfWeek
	Case DayOfWeek.Monday
		tempVar = 0.5D
	Case DayOfWeek.Tuesday
		tempVar = 12.5D
	Case DayOfWeek.Wednesday
		tempVar = 7.5D
	Case DayOfWeek.Thursday
		tempVar = 12.5D
	Case DayOfWeek.Friday
		tempVar = 5.0D
	Case DayOfWeek.Saturday
		tempVar = 2.5D
	Case DayOfWeek.Sunday
		tempVar = 2.0D
	Case Else
		tempVar = 0.0D
End Select
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'static decimal GetDiscountInPercent(System.Nullable(Of DayOfWeek) dayOfWeek)
'{
'	Return tempVar;
'}
VB   C#

Das obige Beispiel behandelt alle möglichen Eingabewerte. Alle Wochentage werden behandelt und stellen den Standardwert dar. Damit werden alle möglichen Werte behandelt. Das Verwerfungsmuster kann nicht als Muster in einem is-Ausdruck oder einer switch-Anweisung verwendet werden. In solchen Fällen können Sie ein var-Muster mit einem Verwerfungszeichen, wie var _, verwenden, um einen beliebigen Ausdruck zu finden. Ein Verwerfungsmuster ist jedoch in einem Switch-Ausdruck zulässig. Weitere Einzelheiten finden Sie im Abschnitt "Verwerfungsmuster" in der Notiz zum Funktionsvorschlag.

Logische Muster

Logische Muster in C# bieten leistungsstarke Werkzeuge für den Musterabgleich, einschließlich Negation, Konjunktion und Disjunktion, die flexiblere und aussagekräftigere Abgleichbedingungen ermöglichen.

Negation (nicht Muster)

Das Negationsmuster, dargestellt durch 'not', passt auf einen Ausdruck, wenn das negierte Muster nicht auf den Ausdruck passt. Dies ist besonders nützlich, um zu prüfen, ob ein Ausdruck nicht null ist, wie unten gezeigt:

if (input is not null)
{
    // ...
}
if (input is not null)
{
    // ...
}
If input IsNot Nothing Then
	' ...
End If
VB   C#

Hier wird der Codeblock ausgeführt, wenn die Eingabe nicht null ist.

Konjunktion (und Muster)

Das konjunktive Muster, das das Schlüsselwort "und" verwendet, passt auf einen Ausdruck, wenn beide Muster auf den Ausdruck passen. Dies ermöglicht die Kombination mehrerer Bedingungen, wie das folgende Beispiel zeigt:

Console.WriteLine(Classify(13));    // output: High
Console.WriteLine(Classify(-100));  // output: Too low
Console.WriteLine(Classify(5.7));   // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -40.0 => "Too low",
    >= -40.0 and < 0 => "Low",
    >= 0 and < 10.0 => "Acceptable",
    >= 10.0 and < 20.0 => "High",
    >= 20.0 => "Too high",
    double.NaN => "Unknown",
};
Console.WriteLine(Classify(13));    // output: High
Console.WriteLine(Classify(-100));  // output: Too low
Console.WriteLine(Classify(5.7));   // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -40.0 => "Too low",
    >= -40.0 and < 0 => "Low",
    >= 0 and < 10.0 => "Acceptable",
    >= 10.0 and < 20.0 => "High",
    >= 20.0 => "Too high",
    double.NaN => "Unknown",
};
Console.WriteLine(Classify(13)) ' output: High
Console.WriteLine(Classify(-100)) ' output: Too low
Console.WriteLine(Classify(5.7)) ' output: Acceptable
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string Classify(double measurement) => measurement switch
'{
'	< -40.0 => "Too low",
'	>= -40.0 and < 0 => "Low",
'	>= 0 and < 10.0 => "Acceptable",
'	>= 10.0 and < 20.0 => "High",
'	>= 20.0 => "Too high",
'	double.NaN => "Unknown",
'};
VB   C#

In diesem Beispiel wird die Messung auf der Grundlage ihres Wertebereichs klassifiziert.

Disjunktiv (oder Muster)

Das disjunktive Muster, das das Schlüsselwort "oder" verwendet, passt auf einen Ausdruck, wenn eines der beiden Muster auf den Ausdruck passt. Auf diese Weise können mehrere mögliche Bedingungen gehandhabt werden, wie unten dargestellt:

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        3 or 4 or 5 => "spring",
        6 or 7 or 8 => "summer",
        9 or 10 or 11 => "autumn",
        12 or 1 or 2 => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        3 or 4 or 5 => "spring",
        6 or 7 or 8 => "summer",
        9 or 10 or 11 => "autumn",
        12 or 1 or 2 => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
Console.WriteLine(GetCalendarSeason(New DateTime(2021, 1, 19))) ' output: winter
	Console.WriteLine(GetCalendarSeason(New DateTime(2021, 10, 9))) ' output: autumn
	Console.WriteLine(GetCalendarSeason(New DateTime(2021, 5, 11))) ' output: spring
	Dim tempVar As String
	Select Case [date].Month
		Case 3, 4, 5
			tempVar = "spring"
		Case 6, 7, 8
			tempVar = "summer"
		Case 9, 10, 11
			tempVar = "autumn"
		Case 12, 1, 2
			tempVar = "winter"
		Case Else
'INSTANT VB TODO TASK: Throw expressions are not converted by Instant VB:
'ORIGINAL LINE: tempVar = throw new ArgumentOutOfRangeException(nameof(date), string.Format("Date with unexpected month: {0}.", date.Month));
			tempVar = throw New ArgumentOutOfRangeException(NameOf([date]), $"Date with unexpected month: {[date].Month}.")
	End Select
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'	static string GetCalendarSeason(DateTime @date)
'	{
'		Return tempVar;
'	}
VB   C#

Hier wird die Kalendersaison auf der Grundlage des Monats des angegebenen Datums bestimmt.

Diese Musterkombinatoren können wiederholt verwendet werden, um komplexere und präzisere Abgleichsbedingungen zu erstellen und so die Flexibilität und Lesbarkeit Ihres Codes zu verbessern.

Muster der Eigenschaft

Das Eigenschaftsmuster ermöglicht den Abgleich der Eigenschaften oder Felder eines Ausdrucks mit verschachtelten Mustern. Ein Beispiel hierfür ist im folgenden Codeausschnitt zu sehen:

static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
Shared Function IsConferenceDay(ByVal [date] As DateTime) As Boolean
'INSTANT VB TODO TASK: The following 'is' operator pattern is not converted by Instant VB:
	Return [date] is { Year: 2020, Month: 5, Day: 19 [or] 20 [or] 21 }
End Function
VB   C#

Hier stellt das Eigenschaftsmuster sicher, dass das angegebene Datum mit einem der angegebenen Konferenztage übereinstimmt.

Sie können auch eine Laufzeittypprüfung und eine Variablendeklaration in ein Eigenschaftsmuster einbauen, wie unten gezeigt:

static string TakeFive(object input) => input switch
{
    string { Length: >= 5 } s => s.Substring(0, 5),
    string s => s,
    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
    ICollection<char> symbols => new string(symbols.ToArray()),
    null => throw new ArgumentNullException(nameof(input)),
    _ => throw new ArgumentException("Unsupported input type."),
};
static string TakeFive(object input) => input switch
{
    string { Length: >= 5 } s => s.Substring(0, 5),
    string s => s,
    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
    ICollection<char> symbols => new string(symbols.ToArray()),
    null => throw new ArgumentNullException(nameof(input)),
    _ => throw new ArgumentException("Unsupported input type."),
};
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string TakeFive(object input) => input switch
'{
'	string { Length: >= 5 } s => s.Substring(0, 5),
'	string s => s,
'	ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
'	ICollection<char> symbols => new string(symbols.ToArray()),
'	null => throw new ArgumentNullException(nameof(input)),
'	_ => throw new ArgumentException("Unsupported input type."),
'};
VB   C#

Hier wird das Eigenschaftsmuster zur Behandlung von Zeichenketten und Zeichensammlungen verwendet, um eine ordnungsgemäße Behandlung auf der Grundlage ihrer Eigenschaften zu gewährleisten.

Positionelles Muster

In C# ermöglicht das Positionsmuster die Dekonstruktion eines Ausdrucksergebnisses und den Abgleich der resultierenden Werte mit entsprechenden verschachtelten Mustern. Zum Beispiel:

public readonly struct Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) => (X, Y) = (x, y);
    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Classify(Point point) => point switch
{
    (0, 0) => "Origin",
    (1, 0) => "Positive X basis end",
    (0, 1) => "Positive Y basis end",
    _ => "Just a point",
};
public readonly struct Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) => (X, Y) = (x, y);
    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Classify(Point point) => point switch
{
    (0, 0) => "Origin",
    (1, 0) => "Positive X basis end",
    (0, 1) => "Positive Y basis end",
    _ => "Just a point",
};
'INSTANT VB WARNING: VB has no equivalent to the C# readonly struct:
'ORIGINAL LINE: public readonly struct Point
Public Structure Point
	Public ReadOnly Property X() As Integer
	Public ReadOnly Property Y() As Integer
	Public Sub New(ByVal x As Integer, ByVal y As Integer)
'INSTANT VB TODO TASK: VB has no equivalent to the C# deconstruction assignments:
		(X, Y) = (x, y)
	End Sub
	Public Sub Deconstruct(<System.Runtime.InteropServices.Out()> ByRef x As Integer, <System.Runtime.InteropServices.Out()> ByRef y As Integer)
'INSTANT VB TODO TASK: VB has no equivalent to the C# deconstruction assignments:
		(x, y) = (X, Y)
	End Sub
End Structure
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string Classify(Point point) => point switch
'{
'	(0, 0) => "Origin",
'	(1, 0) => "Positive X basis end",
'	(0, 1) => "Positive Y basis end",
'	_ => "Just a point",
'};
VB   C#

In diesem Beispiel wird das Positionsmuster verwendet, um Punkte auf der Grundlage ihrer Koordinaten zu klassifizieren.

Außerdem können Sie auf verschachtelte Eigenschaften oder Felder innerhalb eines Eigenschaftsmusters verweisen, das als erweitertes Eigenschaftsmuster bezeichnet wird und in C# 10 eingeführt wurde:

static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };
static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };
Shared Function IsAnyEndOnXAxis(ByVal segment As Segment) As Boolean
'INSTANT VB TODO TASK: The following 'is' operator pattern is not converted by Instant VB:
	Return segment is { Start.Y: 0 } [or] { [End].Y: 0 }
End Function
VB   C#

Diese Funktion erhöht die Flexibilität von Eigenschaftsmustern, indem sie den direkten Zugriff auf verschachtelte Eigenschaften ermöglicht.

Diese Muster bieten leistungsfähige Mechanismen für den Umgang mit komplexen Datenstrukturen und verbessern die Lesbarkeit und Aussagekraft Ihres Codes.

Var-Muster

Mit Var Pattern können Sie jeden Typ abgleichen. Dies kann besonders nützlich sein, um Zwischenergebnisse in booleschen Ausdrücken zu erfassen oder wenn mehrere Prüfungen in switch case guards erforderlich sind.

Das folgende Beispiel demonstriert die Verwendung von var pattern in einem booleschen Ausdruck:

static bool IsAcceptable(int id, int absLimit) =>
    SimulateDataFetch(id) is var results 
    && results.Min() >= -absLimit 
    && results.Max() <= absLimit;
static int [] SimulateDataFetch(int id)
{
    var rand = new Random();
    return Enumerable
               .Range(start: 0, count: 5)
               .Select(s => rand.Next(minValue: -10, maxValue: 11))
               .ToArray();
}
static bool IsAcceptable(int id, int absLimit) =>
    SimulateDataFetch(id) is var results 
    && results.Min() >= -absLimit 
    && results.Max() <= absLimit;
static int [] SimulateDataFetch(int id)
{
    var rand = new Random();
    return Enumerable
               .Range(start: 0, count: 5)
               .Select(s => rand.Next(minValue: -10, maxValue: 11))
               .ToArray();
}
Shared Function IsAcceptable(ByVal id As Integer, ByVal absLimit As Integer) As Boolean
	Dim tempVar As Boolean = TypeOf SimulateDataFetch(id) Is var
	Dim results = If(tempVar, CType(SimulateDataFetch(id), var), Nothing)
	Return tempVar AndAlso results.Min() >= -absLimit AndAlso results.Max() <= absLimit
End Function
Shared Function SimulateDataFetch(ByVal id As Integer) As Integer()
	Dim rand = New Random()
	Return Enumerable.Range(start:= 0, count:= 5).Select(Function(s) rand.Next(minValue:= -10, maxValue:= 11)).ToArray()
End Function
VB   C#

In diesem Beispiel gibt SimulateDataFetch ein Array von Ganzzahlen zurück, und das is var-Muster fängt das Ergebnis in der Ergebnisvariablen ein, was nachfolgende Berechnungen auf der Grundlage ihrer Eigenschaften ermöglicht.

Außerdem können var-Muster innerhalb von switch-Ausdrücken oder -Anweisungen verwendet werden, um den Code prägnanter und lesbarer zu machen. Hier ist ein Beispiel für die Verwendung des var-Musters in switch case guards:

public record Point(int X, int Y);
static Point Transform(Point point) => point switch
{
    var (x, y) when x < y => new Point(-x, y),
    var (x, y) when x > y => new Point(x, -y),
    var (x, y) => new Point(x, y),
};
static void TestTransform()
{
    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }
    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }
}
public record Point(int X, int Y);
static Point Transform(Point point) => point switch
{
    var (x, y) when x < y => new Point(-x, y),
    var (x, y) when x > y => new Point(x, -y),
    var (x, y) => new Point(x, y),
};
static void TestTransform()
{
    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }
    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }
}
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Point(int X, int Y)
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static Point Transform(Point point) => point switch
'{
'	var (x, y) when x < y => new Point(-x, y),
'	var (x, y) when x > y => new Point(x, -y),
'	var (x, y) => new Point(x, y),
'};
Shared Sub TestTransform()
	Console.WriteLine(Transform(New Point(1, 2))) ' output: Point { X = -1, Y = 2 }
	Console.WriteLine(Transform(New Point(5, 2))) ' output: Point { X = 5, Y = -2 }
End Sub
VB   C#

In diesem Beispiel wird das var-Muster (x, y) erfasst die Koordinaten des Punktes und ermöglicht verschiedene Transformationen auf der Grundlage ihrer Werte.

Bei einem var-Muster wird der Typ der deklarierten Variablen aus dem Kompilierzeittyp des Ausdrucks abgeleitet, der mit dem Muster verglichen wird.

Das var-Muster bietet eine bequeme Möglichkeit, mit verschiedenen Szenarien umzugehen, in denen der spezifische Typ des Ausdrucks nicht im Voraus bekannt ist, und verbessert die Klarheit und Flexibilität des Codes.

Einführung in die IronPDF-Bibliothek

IronPDF ist eine Bibliothek von Iron Software, die sich auf die Erstellung von PDF-Dokumenten spezialisiert hat. Um loszulegen, installieren Sie die Bibliothek zunächst über den NuGet-Paketmanager oder den Visual Studio Package Manager

Install-Package IronPdf

Das folgende Bild zeigt, wie die Installation von Visual Studio.

C# Pattern-Matching-Ausdrücke (So funktioniert es für Entwickler): Abbildung 1 - Installation von IronPDF mit dem NuGet-Paketmanager

Im folgenden Code werden wir sehen, wie wir ein einfaches PDF-Dokument erzeugen können:

namespace IronPatterns;
class Program
{
    static void Main()
    {
        Console.WriteLine("-----------Iron Software-------------");
        var renderer = new ChromePdfRenderer(); // var pattern
        var content = " <h1> Iron Software is Awesome </h1> Made with IronPDF!";
        // Declaration Pattern
        int? nullableX = 8;
        int y = 45;
        object boxedy = y;
        content += "<p>Declaration Pattern</p>";
        if (nullableX is int a && boxedy is int b)
        {
            Console.WriteLine(a + b); // output: 53
            content += $"<p>Ouput:{(a + b)}</p>";
        }
        //Relational patterns
        content += "<p>Relational patterns</p>";
        var season1 = GetCalendarSeason(new DateTime(2024, 2, 25));
        Console.WriteLine(season1);
        content += $"<p>2024, 2, 25:{season1}</p>";
        var season2 = GetCalendarSeason(new DateTime(2024, 5, 25));
        Console.WriteLine(season2);
        content += $"<p>2024, 5, 25:{season1}</p>";
        var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
        Console.WriteLine(season3);
        content += $"<p>2024, 7, 25:{season1}</p>";
        var pdf = renderer.RenderHtmlAsPdf(content);
        pdf.SaveAs("output.pdf"); // Saves our PdfDocument object as a PDF        
    }
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        >= 3 and < 6 => "spring",
        >= 6 and < 9 => "summer",
        >= 9 and < 12 => "autumn",
        12 or (>= 1 and < 3) => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
}
namespace IronPatterns;
class Program
{
    static void Main()
    {
        Console.WriteLine("-----------Iron Software-------------");
        var renderer = new ChromePdfRenderer(); // var pattern
        var content = " <h1> Iron Software is Awesome </h1> Made with IronPDF!";
        // Declaration Pattern
        int? nullableX = 8;
        int y = 45;
        object boxedy = y;
        content += "<p>Declaration Pattern</p>";
        if (nullableX is int a && boxedy is int b)
        {
            Console.WriteLine(a + b); // output: 53
            content += $"<p>Ouput:{(a + b)}</p>";
        }
        //Relational patterns
        content += "<p>Relational patterns</p>";
        var season1 = GetCalendarSeason(new DateTime(2024, 2, 25));
        Console.WriteLine(season1);
        content += $"<p>2024, 2, 25:{season1}</p>";
        var season2 = GetCalendarSeason(new DateTime(2024, 5, 25));
        Console.WriteLine(season2);
        content += $"<p>2024, 5, 25:{season1}</p>";
        var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
        Console.WriteLine(season3);
        content += $"<p>2024, 7, 25:{season1}</p>";
        var pdf = renderer.RenderHtmlAsPdf(content);
        pdf.SaveAs("output.pdf"); // Saves our PdfDocument object as a PDF        
    }
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        >= 3 and < 6 => "spring",
        >= 6 and < 9 => "summer",
        >= 9 and < 12 => "autumn",
        12 or (>= 1 and < 3) => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
}
Namespace IronPatterns
	Friend Class Program
		Shared Sub Main()
			Console.WriteLine("-----------Iron Software-------------")
			Dim renderer = New ChromePdfRenderer() ' var pattern
			Dim content = " <h1> Iron Software is Awesome </h1> Made with IronPDF!"
			' Declaration Pattern
			Dim nullableX? As Integer = 8
			Dim y As Integer = 45
			Dim boxedy As Object = y
			content &= "<p>Declaration Pattern</p>"
			Dim tempVar As Boolean = TypeOf boxedy Is Integer
			Dim b As Integer = If(tempVar, DirectCast(boxedy, Integer), Nothing)
			Dim tempVar2 As Boolean = TypeOf nullableX Is Integer
			Dim a As Integer = If(tempVar2, CInt(nullableX), Nothing)
			If tempVar2 AndAlso tempVar Then
				Console.WriteLine(a + b) ' output: 53
				content &= $"<p>Ouput:{(a + b)}</p>"
			End If
			'Relational patterns
			content &= "<p>Relational patterns</p>"
			Dim season1 = GetCalendarSeason(New DateTime(2024, 2, 25))
			Console.WriteLine(season1)
			content &= $"<p>2024, 2, 25:{season1}</p>"
			Dim season2 = GetCalendarSeason(New DateTime(2024, 5, 25))
			Console.WriteLine(season2)
			content &= $"<p>2024, 5, 25:{season1}</p>"
			Dim season3 = GetCalendarSeason(New DateTime(2024, 7, 25))
			Console.WriteLine(season3)
			content &= $"<p>2024, 7, 25:{season1}</p>"
			Dim pdf = renderer.RenderHtmlAsPdf(content)
			pdf.SaveAs("output.pdf") ' Saves our PdfDocument object as a PDF
		End Sub
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'		static string GetCalendarSeason(DateTime date) => date.Month switch
'		{
'			>= 3 and < 6 => "spring",
'			>= 6 and < 9 => "summer",
'			>= 9 and < 12 => "autumn",
'			12 or (>= 1 and < 3) => "winter",
'			_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
'		};
	End Class
End Namespace
VB   C#

Ausgabe

C# Pattern-Matching-Ausdrücke (Wie es für Entwickler funktioniert): Abbildung 2

Code-Details

Wir verwenden hier IronPDF chromePdfRenderer", um die HTML-Zeichenfolge im PDF-Dokument zu speichern. Die Ausgabe wird im Dokument "output.pdf" gespeichert.

Probelizenz

IronPDF kann mit einer Testlizenz verwendet werden, die bei hier. Geben Sie eine E-Mail-ID an, um einen Lizenzschlüssel zu generieren, der Ihnen per E-Mail zugestellt wird.

"IronPDF.LicenseKey": "<Your Key>"
"IronPDF.LicenseKey": "<Your Key>"
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'"IronPDF.LicenseKey": "<Your Key>"
VB   C#

Platzieren Sie den Lizenzschlüssel in der Datei AppSettings.Json wie oben gezeigt.

Schlussfolgerung

Pattern-Matching-Ausdrücke in C# bieten eine leistungsstarke und flexible Möglichkeit, bedingte Anweisungen, Typüberprüfungen und Objektdekonstruktionen in einer prägnanten und lesbaren Weise zu schreiben. Durch den Einsatz von Pattern-Matching können Entwickler die Übersichtlichkeit und Wartbarkeit ihres Codes verbessern und gleichzeitig Floskeln und Redundanzen reduzieren. Ob Typprüfung, Switch-Anweisungen oder Dekonstruktion - Mustervergleichsausdrücke bieten ein vielseitiges Toolset zur Bewältigung einer Vielzahl von Programmieraufgaben in C#.

Zusammenfassend lässt sich sagen, dass die Beherrschung von Pattern-Matching-Ausdrücken Ihre C#-Programmierkenntnisse erheblich verbessern kann und Sie in die Lage versetzt, saubereren, aussagekräftigeren Code zu schreiben, der leichter zu verstehen und zu warten ist. Auch in diesem Artikel haben wir über IronPDF die für die Erstellung von PDF-Dokumenten genutzt werden können.

< PREVIOUS
.NET Software-Entwicklung (Wie es für Entwickler funktioniert)
NÄCHSTES >
C# Intern (Wie es für Entwickler funktioniert)

Sind Sie bereit, loszulegen? Version: 2024.10 gerade veröffentlicht

Gratis NuGet-Download Downloads insgesamt: 11,308,499 Lizenzen anzeigen >