Zum Fußzeileninhalt springen
.NET HILFE

In diesem Artikel tauchen wir tief in die Komplexität des C# LINQ Join-Operators ein und erklären seine Funktionalität, Syntax und Anwendungen.

Mustererkennung in C# ist ein leistungsstarkes Feature, das in C# 7.0 eingeführt und seitdem in nachfolgenden Versionen erweitert wurde. Es ermöglicht Entwicklern, prägnanteren und ausdrucksstärkeren Code zu schreiben, wenn es um bedingte Anweisungen, Typprüfung und die Zerlegung von Objekten geht.

Mustererkennungsausdrü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 der Mustererkennungsausdrücke in C# erkunden, einschließlich Syntax, Anwendungsfällen und Codebeispielen. Am Ende des Artikels werden wir auch ein wenig über IronPDF PDF Erstellung Bibliothek von Iron Software sprechen, um ein PDF-Dokument in C#-Anwendungen spontan zu erstellen.

Vorteile der Mustererkennung in C

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

  • Verbesserte Lesbarkeit: Mustererkennung vereinfacht komplexe bedingte Logik und macht Ihren Code so leichter verständlich und nachvollziehbar – sowohl für Sie selbst als auch für andere Entwickler.
  • Reduzierung der Codezeilen: Durch die Zusammenfassung komplexer bedingter Anweisungen in prägnante Muster trägt das Pattern Matching zur Optimierung Ihrer Codebasis bei, was zu weniger Codezeilen und einer kompakteren Implementierung führt.
  • Verbesserte Wartbarkeit: Die durch Pattern Matching erzielte Klarheit fördert eine einfachere Code-Wartung und Fehlersuche. Mit klar abgegrenzten Mustern wird es einfacher, bestimmte Logikblöcke bei Bedarf zu identifizieren und zu ändern, ohne den restlichen Code zu beeinträchtigen.
  • Ausdrucksstärkere Algorithmen: Mustererkennung versetzt Entwickler in die Lage, Algorithmen auf natürlichere und intuitivere Weise auszudrücken. Durch die Ausrichtung von Code-Strukturen auf Problemlösungs-Paradigmen erleichtert die Mustererkennung die Erstellung von Algorithmen, die ihren konzeptuellen Modellen sehr nahe kommen.

Typen der Mustererkennung in C

Mustererkennung wird durch folgende Ausdrücke unterstützt:

  • is Ausdruck
  • switch Aussagen
  • switch Ausdrücke

Die folgenden Muster können zum Abgleich mit den Konstrukten verwendet werden:

Deklaration und Typenmuster

Deklarations- und Typenmuster sind wesentliche Werkzeuge in C#, um die Kompatibilität von Ausführungszeit-Typen von Ausdrücken mit gegebenen Typen zu überprüfen. Mit Deklarationsmustern können Sie sowohl die Kompatibilität prüfen als auch gleichzeitig eine neue lokale Variable deklarieren. Beispiel: IronPDF rendert HTML zu einem PDF und speichert es.

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
$vbLabelText   $csharpLabel

Das Deklarationsmuster stellt hier sicher, dass, wenn der Ausdruck greeting dem Typ string entspricht, er der Variablen message zugewiesen wird, wodurch nachfolgende Operationen ermöglicht werden.

Wenn eine der folgenden Bedingungen zutrifft, hält das Deklarationsmuster stand:

  • 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 Nullable-Werttyp mit dem zugrunde liegenden Typ T.
  • Es existiert eine Boxing- oder Unboxing-Konvertierung vom Laufzeittyp des Ausdrucks zum Typ T.

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

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
$vbLabelText   $csharpLabel

Hier entspricht nullableX dem Muster, weil es sich um einen Nullable-Werttyp mit dem zugrunde liegenden Typ int handelt, und boxedy entspricht dem Muster, weil es zu int entpackt werden kann.

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

public static decimal CalculateToll(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(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(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)),
'};
$vbLabelText   $csharpLabel

In diesem Codeausschnitt dient _ als Platzhalter für jeden Typ, der Vehicle entspricht.

Sowohl Deklarations- als auch Typenmuster stellen sicher, dass Ausdrücke vor der Mustererkennung nicht null sind. Sie können auf Nicht-Null prüfen, indem Sie ein verneintes Nullkonstantenmuster verwenden, wie unten gezeigt:

if (inputVal is not null)
{
    // ...
}
if (inputVal is not null)
{
    // ...
}
If inputVal IsNot Nothing Then
	' ...
End If
$vbLabelText   $csharpLabel

Diese Negation stellt sicher, dass inputVal nicht null ist, bevor mit weiteren Operationen fortgefahren wird.

Durch den Einsatz von Deklarations- und Typenmustern 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 Möglichkeit zur Handhabung typbasierter Logik und verbessern die Wartbarkeit Ihrer Codebasis.

Konstante Muster

Konstantenmuster dienen dazu, zu überprüfen, ob ein Ausdrucksergebnis einem bestimmten Konstantenwert entspricht. Beispiel: IronPDF rendert HTML zu einem PDF und speichert es.

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;
'}
$vbLabelText   $csharpLabel

Hier wird anhand konstanter Muster geprüft, ob visitorCount mit einem der angegebenen konstanten Werte übereinstimmt, und es werden die entsprechenden Ticketpreise zurückgegeben.

In einem Konstantenmuster können Sie verschiedene Arten von Konstantenausdrücken verwenden, wie:

  1. Ganze oder Fließkomma-Zahlenliterale.
  2. Zeichen.
  3. Zeichenfolgenliterale.
  4. Boolesche Werte (true oder false).
  5. Enumerationswerte.
  6. Der Name eines deklarierten Const-Felds oder lokals.
  7. null.

Ein Ausdruck vom Typ Span<char> oder ReadOnlySpan<char> kann konstante Zeichenketten abgleichen.

Um auf null zu prüfen, verwenden Sie ein konstantes Muster wie folgt:

if (inputVal is null)
{
    return;
}
if (inputVal is null)
{
    return;
}
If inputVal Is Nothing Then
	Return
End If
$vbLabelText   $csharpLabel

Das Muster stellt hier sicher, dass inputVal null ist, bevor mit weiteren Operationen fortgefahren wird.

Sie können auch ein verneintes Nullkonstantenmuster verwenden, um nicht-null Werte zu bestimmen:

if (inputVal is not null)
{
    // ...
}
if (inputVal is not null)
{
    // ...
}
If inputVal IsNot Nothing Then
	' ...
End If
$vbLabelText   $csharpLabel

Dieses Muster überprüft, ob inputVal nicht null ist, sodass nachfolgende Operationen sicher durchgeführt werden können.

Indem Sie Konstantenmuster in Ihren C#-Code integrieren, können Sie Szenarien effektiv verwalten, in denen bestimmte Konstantenwerte abgeglichen werden müssen, wodurch die Codeklarheit und Wartbarkeit verbessert wird.

Relationale Schemata

Relationale Muster bieten eine Möglichkeit, Ausdrucksergebnisse mit Konstanten zu vergleichen. Beispiel: IronPDF rendert HTML zu einem PDF und speichert es.

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",
'};
$vbLabelText   $csharpLabel

Hier werden die relationalen Muster mit measurement anhand spezifischer Schwellenwerte verglichen, um ihre Klassifizierung zu bestimmen.

Der rechte Teil eines relationalen Musters muss ein konstanter Ausdruck sein, der vom Typ Integer, Gleitkommazahl, char oder enum sein kann. Die Operatoren <, >, <=, >= können auf der linken Seite verwendet werden.

Um ein Ausdrucksergebnis innerhalb eines bestimmten Bereichs abzugleichen, verwenden Sie ein konjunktives "und"-Muster, wie unten illustriert:

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}."),
'};
$vbLabelText   $csharpLabel

Dieser Abschnitt beschreibt, wie das konjunktive "und"-Muster genutzt wird, um die Kalenderjahreszeit basierend auf dem innerhalb bestimmter Bereiche liegenden Monat zu bestimmen. Es wird auch erwähnt, dass relationale Muster eine prägnante und ausdrucksstarke Mittel bieten, um Ausdrucksergebnisse gegen Konstanten zu vergleichen, wodurch die Codeklarheit und Wartbarkeit verbessert wird.

Muster verwerfen

Das Verwerfungsmuster, bezeichnet durch _, dient dazu, jeden Ausdruck abzugleichen, einschließlich null. Betrachten 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;
'}
$vbLabelText   $csharpLabel

Im oberen Discard-Musterbeispiel werden alle möglichen Eingabewerte behandelt. Alle Wochentage werden verwaltet, und ein Standardwert wird bereitgestellt. Damit werden alle möglichen Werte verarbeitet. Das Discard-Muster kann nicht als Muster in einem is Ausdruck oder einer switch Anweisung verwendet werden. In solchen Fällen kann ein var Muster mit einem Verwerfungszeichen wie var _ verwendet werden, um jeden Ausdruck abzugleichen. Allerdings ist ein Discard-Muster in einem switch Ausdruck zulässig. Für weitere Details beachten Sie bitte den Discard-Musterabschnitt des Feature-Vorschlags.

Logische Muster

Logische Muster in C# bieten leistungsstarke Werkzeuge zur Mustererkennung, einschließlich Negation, Konjunktion und Disjunktion, die flexiblere und ausdrucksstärkere Vergleichsbedingungen ermöglichen.

Negation (not pattern)

Das Negationsmuster, dargestellt durch not, passt zu einem Ausdruck, wenn das negierte Muster nicht mit dem Ausdruck übereinstimmt. Dies ist besonders nützlich, um zu überprüfen, ob ein Ausdruck nicht null ist, wie unten demonstriert:

if (input is not null)
{
    // ...
}
if (input is not null)
{
    // ...
}
If input IsNot Nothing Then
	' ...
End If
$vbLabelText   $csharpLabel

Hier wird der Codeblock ausgeführt, falls input nicht null ist.

Konjunktiv (and Muster)

Das konjunktive Muster, das das Schlüsselwort and verwendet, passt zu einem Ausdruck, wenn beide Muster mit dem Ausdruck übereinstimmen. Dies ermöglicht das Kombinieren mehrerer Bedingungen, wie im folgenden Beispiel illustriert:

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",
'};
$vbLabelText   $csharpLabel

In diesem Beispiel wird der measurement anhand seines Wertebereichs klassifiziert.

Disjunktiv (or Muster)

Das disjunktive Muster, das das Schlüsselwort or verwendet, findet eine Übereinstimmung mit einem Ausdruck, wenn eines der beiden Muster mit dem Ausdruck übereinstimmt. Dies ermöglicht das Verarbeiten mehrerer möglicher Bedingungen, wie unten gezeigt:

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;
'}
$vbLabelText   $csharpLabel

Hier wird die Kalenderjahreszeit basierend auf dem Monat des angegebenen Datums bestimmt.

Diese Musterkombinatoren können wiederholt verwendet werden, um komplexere und präzisere Vergleichsbedingungen zu erstellen, wodurch die Flexibilität und Lesbarkeit Ihres Codes verbessert wird.

Eigenschaftsmuster

Das Property-Muster ermöglicht den Vergleich der Eigenschaften oder Felder eines Ausdrucks mit verschachtelten Mustern. Ein Beispiel dafür sehen Sie im folgenden Code-Schnipsel:

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
$vbLabelText   $csharpLabel

Hier stellt das Property-Muster sicher, dass das angegebene Datum einem der angegebenen Konferenztage entspricht.

Sie können auch eine Laufzeit Typenüberprüfung und Deklaration einer Variablen innerhalb eines Property-Musters 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."),
'};
$vbLabelText   $csharpLabel

Hier wird das Property-Muster verwendet, um Zeichenfolgen und Zeichensammlungen zu behandeln, um eine ordnungsgemäße Handhabung basierend auf ihren Eigenschaften zu gewährleisten.

Positionsmuster

In C# ermöglicht das Positionsmuster das Zerlegen 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",
'};
$vbLabelText   $csharpLabel

In diesem Beispiel wird das Positionsmuster verwendet, um Punkte basierend auf ihren Koordinaten zu klassifizieren.

Darüber hinaus können Sie innerhalb eines Property-Musters auf verschachtelte Eigenschaften oder Felder verweisen, das als erweitertes Property-Muster bekannt ist, das 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
$vbLabelText   $csharpLabel

Dieses Feature verbessert die Flexibilität der Property-Muster, indem es den direkten Zugriff auf verschachtelte Eigenschaften ermöglicht.

Diese Muster bieten mächtige Mechanismen zum Umgang mit komplexen Datenstrukturen und zur Verbesserung der Lesbarkeit und Ausdruckskraft Ihres Codes.

Var-Muster

Var-Muster ermöglicht es, einen beliebigen Typ abzugleichen. Dies kann besonders nützlich sein, um Zwischenresultate innerhalb von Booleschen Ausdrücken zu erfassen oder wenn in Schutzwächtern von Switch-Anweisungen mehrere Prüfungen erforderlich sind.

Hier ist ein Beispiel, das die Verwendung des Var-Musters in einem Booleschen Ausdruck demonstriert:

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
$vbLabelText   $csharpLabel

In diesem Beispiel gibt SimulateDataFetch ein Array von ganzen Zahlen zurück, und das Muster is var speichert das Ergebnis in der Variablen results, wodurch nachfolgende Berechnungen auf Basis ihrer Eigenschaften möglich sind.

Darüber hinaus können Var-Muster in Switch-Ausdrücken oder -Anweisungen für prägnanteren Code verwendet werden. Beispiel für die Verwendung von Var-Mustern in Switch-Fall-Schutzwächtern:

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
$vbLabelText   $csharpLabel

In diesem Beispiel erfasst das Variablenmuster (x, y) die Koordinaten des Punktes und ermöglicht so verschiedene Transformationen basierend auf deren Werten.

In einem Var-Muster wird der Typ der deklarierten Variable aus dem Kompilierungszeit-Typ des Ausdrucks, der mit dem Muster abgeglichen wird, abgeleitet.

Das Var-Muster bietet eine bequeme Möglichkeit, verschiedene Szenarien zu bewältigen, in denen der spezifische Ausdruckstyp nicht im Voraus bekannt ist, und verbessert so die Codeklarheit und Flexibilität.

Einführung in die IronPDF-Bibliothek

IronPDF-Dokumenten-Rendering ist eine Bibliothek von Iron Software, die sich auf die Erstellung von PDF-Dokumenten spezialisiert hat. Um loszulegen, muss die Bibliothek zunächst aus dem NuGet-Paketmanager oder aus dem Visual Studio Paket-Manager installiert werden.

# To install from the NuGet Package Manager Console
Install-Package IronPdf
# To install from the NuGet Package Manager Console
Install-Package IronPdf
SHELL

Das folgende Bild zeigt, wie man aus dem Visual Studio Installationshandbuch installiert.

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

Im nachfolgenden Code sehen wir, wie man ein einfaches PDF-Dokument erstellt:

using IronPdf;

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>Output: {(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: {season2}</p>";
            var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
            Console.WriteLine(season3);
            content += $"<p>2024, 7, 25: {season3}</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}."),
        };
    }
}
using IronPdf;

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>Output: {(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: {season2}</p>";
            var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
            Console.WriteLine(season3);
            content += $"<p>2024, 7, 25: {season3}</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}."),
        };
    }
}
Imports IronPdf

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>Output: {(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: {season2}</p>"
			Dim season3 = GetCalendarSeason(New DateTime(2024, 7, 25))
			Console.WriteLine(season3)
			content &= $"<p>2024, 7, 25: {season3}</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
$vbLabelText   $csharpLabel

Ausgabe

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

Details zum Code

Hier verwenden wir die Klasse ChromePdfRenderer von IronPDF , um die HTML-Zeichenkette in einem PDF-Dokument zu speichern. Das Ausgabedokument wird im Dokument "output.pdf" gespeichert.

Probelizenz

IronPDF kann mit einer Testlizenz verwendet werden, die von der IronPDF-Lizenzseite bezogen werden kann. Geben Sie eine E-Mail-Adresse an, um einen Lizenzschlüssel zu generieren, der an Ihre E-Mail-Adresse gesendet wird.

"IronPdf.LicenseKey": "<Your Key>"
"IronPdf.LicenseKey": "<Your Key>"
"IronPdf.LicenseKey" = "<Your Key>"
$vbLabelText   $csharpLabel

Fügen Sie den Lizenzschlüssel wie oben gezeigt in die Datei appsettings.json ein.

Abschluss

Mustererkennungsausdrücke in C# bieten eine leistungsstarke und flexible Möglichkeit, bedingte Anweisungen, Typüberprüfungen und Objektdestruktionen auf prägnante und lesbare Weise zu schreiben. Durch die Nutzung der Mustererkennung können Entwickler die Klarheit und Wartbarkeit ihres Codes verbessern, während Boilerplate und Redundanz reduziert werden. Ob Typübermittlung, Switch-Anweisungen oder Destruktion, Mustererkennungsausdrücke bieten ein vielseitiges Werkzeugset zur Bewältigung einer Vielzahl von Programmieraufgaben in C#.

Abschließend kann das Meistern von Mustererkennungsausdrücken Ihre C#-Programmierfähigkeiten erheblich verbessern, sodass Sie saubereren, ausdrucksstärkeren Code schreiben können, der einfacher zu verstehen und zu pflegen ist. Wir haben auch die HTML-zu-PDF-Generierungsfähigkeiten von IronPDF behandelt, die zur Erstellung von PDF-Dokumenten genutzt werden können.

Häufig gestellte Fragen

Wie kann ich Musterabgleich verwenden, um die Lesbarkeit des Codes in C# zu verbessern?

Musterabgleich in C# ermöglicht es Entwicklern, prägnanteren und ausdrucksstärkeren Code zu schreiben, was bedingte Anweisungen klarer und leichter verständlich macht. Dies verbessert die Lesbarkeit und Wartbarkeit, indem die Komplexität von Codeblöcken reduziert wird.

Welche verschiedenen Arten von Musterabgleichsausdrücken sind in C# verfügbar?

C# unterstützt verschiedene Musterabgleichsausdrücke, einschließlich is-Ausdrücken, switch-Anweisungen und switch-Ausdrücken. Jeder Typ bietet unterschiedliche Möglichkeiten, Ausdrücke zu bewerten und Code basierend auf übereinstimmenden Mustern auszuführen.

Wie kann ich PDF-Dokumente mit C# erstellen?

Sie können IronPDF, eine Bibliothek von Iron Software, verwenden, um PDF-Dokumente in C# zu erstellen. Es ermöglicht die Umwandlung von HTML-Inhalten in PDF und ist einfach über NuGet zu installieren, mit einem breiten Spektrum an PDF-Erstellungsfunktionen.

Was sind Deklarations- und Typmuster im C#-Musterabgleich?

Deklarations- und Typmuster in C# überprüfen, ob der Laufzeittyp eines Ausdrucks einem bestimmten Typ entspricht und ermöglichen die Deklaration einer neuen lokalen Variablen, wenn eine Übereinstimmung erfolgreich ist, wodurch typsichere Operationen erleichtert werden.

Wie funktionieren Konstantenmuster in C#?

Konstantenmuster in C# werden verwendet, um zu prüfen, ob ein Ausdruck einem bestimmten konstanten Wert, wie einer Ganzzahl oder einem String, entspricht und bestimmte Logik auszuführen, wenn eine Übereinstimmung gefunden wird. Dies ermöglicht einfache Vergleiche von Konstantenwerten.

Was ist der Zweck von relationalen Mustern in C#?

Relationale Muster in C# ermöglichen es, Ausdrücke mit Konstanten unter Verwendung von relationalen Operatoren wie <, >, <= und >= zu vergleichen. Dies ist nützlich, um prägnante Bereichsüberprüfungen im Code zu implementieren.

Wie können logische Muster in C# angewendet werden?

Logische Muster in C# kombinieren andere Muster mit logischen Operatoren wie and, or und not, was komplexe Musterabgleichbedingungen ermöglicht, die mehrere Kriterien gleichzeitig auswerten können.

Was ist das Wegwerfmuster in C# und wann wird es verwendet?

Das Wegwerfmuster in C#, dargestellt durch _, stimmt mit jedem Ausdruck überein, einschließlich null, und wird häufig in Situationen verwendet, in denen bestimmte Werte ignoriert werden müssen, wie in switch-Ausdrücken.

Wie können Eigenschaftsmuster in C# verwendet werden?

Eigenschaftsmuster in C# ermöglichen es Entwicklern, die Eigenschaften oder Felder eines Objekts gegen verschachtelte Muster abzugleichen, was eine Möglichkeit bietet, tiefe Überprüfungen in der Struktur eines Objekts durchzuführen, während der Code klar und prägnant bleibt.

Jacob Mellor, Chief Technology Officer @ Team Iron
Chief Technology Officer

Jacob Mellor ist Chief Technology Officer bei Iron Software und ein visionärer Ingenieur, der Pionierarbeit in der C# PDF-Technologie leistet. Als der ursprüngliche Entwickler hinter der Kern-Codebasis von Iron Software hat er die Produktarchitektur des Unternehmens seit seiner Gründung geprägt und es zusammen mit CEO ...

Weiterlesen

Iron Support Team

Wir sind 24 Stunden am Tag, 5 Tage die Woche online.
Chat
E-Mail
Rufen Sie mich an