Wyrażenia dopasowujące wzorce w języku C# (jak to działa dla programistów)
Dopasowanie wzorców w C# jest potężną funkcją, która została wprowadzona w C# 7.0 i od tego czasu został poszerzona w kolejnych wersjach. Pozwala programistom pisać bardziej zwięzły i wyrazisty kod przy obsłudze instrukcji warunkowych, sprawdzania typów oraz dekonstrukcji obiektów.
Wyrażenia dopasowania wzorców zapewniają elastyczny i intuicyjny sposób dopasowywania wartości do wzorców oraz wykonywania odpowiadających im bloków kodu. W tym artykule zgłębimy szczegóły wyrażeń dopasowania wzorców w C#, w tym składnię, przypadki użycia i przykłady kodu. Na końcu artykułu zbadamy również trochę o bibliotece generowania PDF IronPDF od Iron Software, aby dynamicznie generować dokumenty PDF w aplikacjach C#.
Zalety dopasowania wzorców w C
Dopasowanie wzorców w kodzie C# ma wiele zalet:
- Zwiększona czytelność: Dopasowanie wzorców upraszcza złożoną logikę warunkową, ułatwiając zrozumienie i śledzenie kodu zarówno sobie, jak i innym programistom.
- Redukcja linii kodu: Skracając złożone instrukcje warunkowe do zwięzłych wzorców, dopasowanie wzorców pomaga usprawnić bazę kodu, prowadząc do mniejszej liczby linii kodu i bardziej zwięzłej implementacji.
- Lepsza utrzymywalność: Klarowność oferowana przez dopasowanie wzorców ułatwia konserwację i debugowanie kodu. Przy wyraźnie wyodrębnionych wzorcach łatwiej jest identyfikować i modyfikować konkretne bloki logiczne zgodnie z potrzebami, bez wpływu na resztę bazy kodu.
- Więcej wyrazistych algorytmów: Dopasowanie wzorców umożliwia programistom wyrażanie algorytmów w sposób bardziej naturalny i intuicyjny. Dopasowując struktury kodu do paradygmatów rozwiązywania problemów, dopasowanie wzorców ułatwia tworzenie algorytmów, które ściśle przypominają swoje modele koncepcyjne.
Typy dopasowania wzorców w C
Dopasowanie wzorców jest obsługiwane przez następujące wyrażenia:
iswyrażenieswitchinstrukcjeswitchwyrażenia
Następujące wzorce mogą być używane do dopasowania do konstrukcji:
Wzorce deklaracji i typów
Wzorce deklaracji i typów są istotnymi narzędziami w C# do sprawdzania zgodności typów wyrażenia w czasie wykonania z podanymi typami. Dzięki wzorcom deklaracji można jednocześnie sprawdzić zgodność i zadeklarować nową zmienną lokalną. Rozważmy następujący przykład:
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
Tutaj wzorzec deklaracji zapewnia, że jeśli wyrażenie greeting pasuje do typu string, zostaje przypisane do zmiennej message, umożliwiając kolejne operacje.
Gdy spełnione są jakiekolwiek z poniższych warunków, wzorzec deklaracji jest prawidłowy:
- Typ wyrażenia w czasie wykonania to
T. - Typ wyrażenia w czasie wykonania pochodzi od
T, implementuje interfejsTlub można go niejawnie przekształcić doT. - Typ wyrażenia w czasie wykonania to nullable value type z podtypem
T. - Istnieje konwersja boksowania lub unboksowania od typu wyrażenia w czasie wykonania do typu
T.
Rozważ poniższy przykład demonstrujący powyższe warunki:
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
Tutaj nullableX pasuje do wzorca, ponieważ jest typem nullable value type z podtypem int, a boxedy pasuje, ponieważ można go unboksować do int.
Jeśli potrzebujesz tylko sprawdzić typ wyrażenia bez deklarowania nowej zmiennej, możesz użyć odrzutu _, jak pokazano na przykładzie poniżej:
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)),
'};
W tym fragmencie _ służy jako zastępnik dla każdego typu pasującego do Vehicle.
Zarówno wzorce deklaracji, jak i typów zapewniają, że wyrażenia nie są puste przed dopasowaniem wzorców. Możesz sprawdzić brak pustego używając zanegowanego wzorca stałej null, jak pokazano poniżej:
if (inputVal is not null)
{
// ...
}
if (inputVal is not null)
{
// ...
}
If inputVal IsNot Nothing Then
' ...
End If
To zanegowanie zapewnia, że inputVal nie jest null przed przystąpieniem do dalszych operacji.
Korzystając z wzorców deklaracji i typów w swoim kodzie C#, możesz zwiększyć czytelność, zredukować liczbę linii kodu i efektywniej wyrażać algorytmy. Te wzorce dostarczają zwięzły i wyrazisty sposób na obsługę logiki opartej na typach i poprawiają utrzymywalność bazy kodu.
Wzorzec stałej
Wzorce stałej służą do sprawdzenia, czy wynik wyrażenia pasuje do określonej wartości stałej. Rozważmy następujący przykład:
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;
'}
Tutaj wzorce stałej sprawdzają, czy visitorCount pasuje do któregokolwiek z określonych wartości stałych i zwracają odpowiadające im ceny biletów.
W wzorcu stałej można używać różnych rodzajów stałych wyrażeń, takich jak:
- Całkowite lub zmiennoprzecinkowe literały numeryczne.
- Znaki.
- Literały znakowe.
- Wartości logiczne (
truelubfalse). - Wartości wyliczeniowe.
- Nazwa zadeklarowanego pola const lub lokalnego.
null.
Wyrażenie typu Span<char> lub ReadOnlySpan<char> może pasować do stałych ciągów.
Aby sprawdzić null, użyj wzorca stałej w ten sposób:
if (inputVal is null)
{
return;
}
if (inputVal is null)
{
return;
}
If inputVal Is Nothing Then
Return
End If
Tutaj wzorzec zapewnia, że inputVal jest null przed przystąpieniem do dalszych operacji.
Możesz również użyć zanegowanego wzorca stałej null, aby stwierdzić brak pustki:
if (inputVal is not null)
{
// ...
}
if (inputVal is not null)
{
// ...
}
If inputVal IsNot Nothing Then
' ...
End If
Ten wzorzec sprawdza, że inputVal nie jest null, co pozwala na wykonywanie kolejnych operacji bezpiecznie.
Włączając wzorce stałej do swojego kodu C#, możesz efektywnie obsługiwać scenariusze, w których konieczne jest dopasowanie do określonych wartości stałych, poprawiając klarowność i utrzymywalność kodu.
Wzorce relacyjne
Wzorce relacyjne zapewniają sposób porównywania wyników wyrażeń ze stałymi. Rozważmy następujący przykład:
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",
'};
Tutaj wzorce relacyjne porównują measurement do określonych progów w celu określenia jego klasyfikacji.
Prawa część wzorca relacyjnego musi być wyrażeniem stałej, które może być typu całkowitego, zmiennoprzecinkowego, char lub enum. Operatorzy <, >, <=, >= mogą być używani po lewej stronie.
Aby dopasować wynik wyrażenia do określonego zakresu, użyj koniunkcyjnego wzorca 'i', jak pokazano poniżej:
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}."),
'};
Ten fragment opisuje, jak koniunkcyjny wzorzec 'i' jest używany do ustalenia pory kalendarzowej na podstawie miesiąca w konkretnych zakresach. Wzmiankuje również, że wzorce relacyjne zapewniają zwięzły i wyrazisty sposób na porównywanie wyników wyrażeń ze stałymi, poprawiając klarowność i utrzymywalność kodu.
Wzorzec odrzucenia
Wzorzec odrzucenia, oznaczony _, służy do dopasowania każdego wyrażenia, w tym null. Oto przykład:
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;
'}
W powyższym przykładzie wzorca odrzucenia obsługiwane są wszystkie możliwe wartości wejściowe. Obsługiwane są wszystkie dni tygodnia, a domyślna wartość jest zapewniana. W ten sposób obsługiwane są wszystkie możliwe wartości. Wzorzec odrzucenia nie może być używany jako wzorzec w is wyrażeniu ani switch instrukcji. W takich przypadkach może być używany wzorzec var z odrzutem, jak var _, do dopasowania dowolnego wyrażenia. Jednak wzorzec odrzucenia jest dopuszczalny w switch wyrażeniu. Więcej informacji znajduje się w sekcji wzorca odrzucenia w notatce propozycji funkcji.
Wzorce logiczne
Wzorce logiczne w C# oferują potężne narzędzia do dopasowania wzorców, w tym negację, koniunkcję i alternatywę, co pozwala na bardziej elastyczne i wyraziste warunki dopasowania.
Negacja (not wzorzec)
Wzór negacji, reprezentowany przez not, pasuje do wyrażenia, gdy zanegowany wzorzec nie pasuje do wyrażenia. Jest to szczególnie przydatne do sprawdzania, czy wyrażenie nie jest puste, jak pokazano poniżej:
if (input is not null)
{
// ...
}
if (input is not null)
{
// ...
}
If input IsNot Nothing Then
' ...
End If
Tutaj blok kodu jest wykonywany, jeśli input nie jest null.
Koniunkcyjny (and wzorzec)
Koniunkcyjny wzorzec, używający słowa kluczowego and, pasuje do wyrażenia, gdy oba wzorce pasują do wyrażenia. To pozwala na łączenie wielu warunków, co ilustruje poniższy przykład:
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",
'};
W tym przykładzie measurement jest klasyfikowany na podstawie jego zakresu wartości.
Alternatywa (or wzorzec)
Alternatywny wzorzec, używający słowa kluczowego or, pasuje do wyrażenia, gdy którekolwiek z wzorców pasuje do wyrażenia. To pozwala na obsługę wielu możliwych warunków, jak pokazano poniżej:
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;
'}
Tutaj pora kalendarzowa jest określana na podstawie miesiąca podanej daty.
Te łączniki wzorców mogą być wielokrotnie używane do tworzenia bardziej złożonych i precyzyjnych warunków dopasowania, zwiększając elastyczność i czytelność kodu.
Wzorzec właściwości
Wzorzec właściwości umożliwia dopasowywanie właściwości lub pól wyrażenia do zagnieżdżonych wzorców. Przykład tego można zobaczyć w poniższym fragmencie kodu:
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
Tutaj wzorzec właściwości zapewnia, że podana data odpowiada jednemu z określonych dni konferencyjnych.
Możesz również połączyć sprawdzenie typu w czasie wykonania z deklaracją zmiennej w ramach wzorca właściwości, jak pokazano poniżej:
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."),
'};
Tutaj wzorzec właściwości jest używany do obsługi ciągów znaków i kolekcji znaków, zapewniając właściwą obsługę na podstawie ich właściwości.
Wzorzec pozycyjny
W C# wzorzec pozycyjny pozwala na dekonstrukcję wyniku wyrażenia i dopasowanie wynikowych wartości do odpowiadających im zagnieżdżonych wzorców. Na przykład:
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",
'};
W tym przykładzie wzorzec pozycyjny jest używany do klasyfikacji punktów na podstawie ich współrzędnych.
Ponadto możesz odnieść się do zagnieżdżonych właściwości lub pól w ramach wzorca właściwości, znanego jako rozszerzony wzorzec właściwości, wprowadzonego w C# 10:
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
Ta funkcja zwiększa elastyczność wzorców właściwości poprzez umożliwienie bezpośredniego dostępu do zagnieżdżonych właściwości.
Te wzorce dostarczają potężnych mechanizmów do obsługi złożonych struktur danych i poprawy czytelności i wyrazistości kodu.
Wzorzec var
Wzorzec var pozwala na dopasowanie dowolnego typu. To może być szczególnie przydatne do uchwycenia wyników pośrednich w wyrażeniach logicznych lub gdy wymagane jest wiele sprawdzeń w ochronnikach case przełącznika.
Oto przykład ilustrujący użycie wzorca var w wyrażeniu logicznym:
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
W tym przykładzie SimulateDataFetch zwraca tablicę liczb całkowitych, a wzorzec is var przechwytuje wynik w zmiennej results, umożliwiając kolejne obliczenia na podstawie jej właściwości.
Ponadto wzorce var mogą być używane w wyrażeniach lub instrukcjach przełącznika dla zwięzłego i czytelnego kodu. Oto przykład użycia wzorca var w ochronnikach case przełącznika:
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
W tym przykładzie wzorzec var (x, y) przechwytuje współrzędne punktu, umożliwiając różne transformacje na ich podstawie.
W wzorcu var typ deklarowanej zmiennej jest wywnioskowany z typu wyrażenia w czasie kompilacji, które jest dopasowywane do wzorca.
Wzorzec var dostarcza wygodnego sposobu na obsługę różnych scenariuszy, w których specyficzny typ wyrażenia nie jest z góry znany, poprawiając klarowność i elastyczność kodu.
Przedstawiamy bibliotekę IronPDF
IronPDF Document Rendering to biblioteka od Iron Software specjalizująca się w generowaniu dokumentów PDF. Aby rozpocząć, pierwszym krokiem jest instalacja biblioteki z menedżera pakietów NuGet lub z menedżera pakietów Visual Studio.
# To install from the NuGet Package Manager Console
Install-Package IronPdf
# To install from the NuGet Package Manager Console
Install-Package IronPdf
Poniższy obrazek pokazuje, jak zainstalować z Visual Studio Przewodnik instalacji.

W poniższym kodzie zobaczymy, jak wygenerować prosty dokument PDF:
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
Wynik

Szczegóły kodu
Tutaj używamy klasy ChromePdfRenderer IronPDF, aby zapisać ciąg HTML do dokumentu PDF. Wynik jest zapisywany w "output.pdf".
Licencja Trial
IronPDF może być używany z licencją trial uzyskaną z Strony licencji IronPDF. Podaj identyfikator e-mail, aby wygenerować klucz licencyjny, który zostanie dostarczony na Twój adres e-mail.
"IronPdf.LicenseKey": "<Your Key>"
"IronPdf.LicenseKey": "<Your Key>"
"IronPdf.LicenseKey" = "<Your Key>"
Umieść klucz licencyjny w pliku appsettings.json, jak pokazano powyżej.
Wnioski
Wyrażenia dopasowania wzorców w C# oferują potężny i elastyczny sposób pisania instrukcji warunkowych, sprawdzania typów oraz dekonstrukcji obiektów w sposób zwięzły i czytelny. Korzystając z dopasowania wzorców, deweloperzy mogą zwiększyć klarowność i utrzymywalność swojego kodu, minimalizując nadmiarowość i szablonowość. Niezależnie od tego, czy chodzi o sprawdzanie typów, instrukcje przełączające, czy dekonstrukcję, wyrażenia dopasowania wzorców zapewniają wszechstronny zestaw narzędzi do rozwiązywania szerokiego zakresu zadań programistycznych w C#.
Podsumowując, opanowanie wyrażeń dopasowania wzorców może znacznie poprawić Twoje umiejętności programowania w C#, umożliwiając pisanie czystszego, bardziej wyrazistego kodu, który jest łatwiejszy do zrozumienia i utrzymania. Omówiliśmy również możliwości generowania HTML do PDF za pomocą IronPDF, które można wykorzystać do generowania dokumentów PDF.
Często Zadawane Pytania
Jak mogę wykorzystać dopasowywanie wzorców, aby poprawić czytelność kodu w języku C#?
Dopasowywanie wzorców w języku C# pozwala programistom pisać bardziej zwięzły i wyrazisty kod, dzięki czemu instrukcje warunkowe są jaśniejsze i łatwiejsze do zrozumienia. Poprawia to czytelność i łatwość konserwacji poprzez zmniejszenie złożoności bloków kodu.
Jakie są różne typy wyrażeń dopasowujących wzorce dostępne w języku C#?
Język C# obsługuje różne wyrażenia dopasowujące wzorce, w tym wyrażenia is, instrukcje switch oraz wyrażenia switch. Każdy typ zapewnia inne sposoby oceny wyrażeń i wykonywania kodu w oparciu o dopasowane wzorce.
Jak mogę generować dokumenty PDF przy użyciu języka C#?
Możesz użyć IronPDF, biblioteki firmy Iron Software, do generowania dokumentów PDF w języku C#. Umożliwia ona konwersję treści HTML do formatu PDF i jest łatwa w instalacji za pośrednictwem NuGet, oferując szeroki zakres funkcji generowania plików PDF.
Czym są wzorce deklaracji i typów w dopasowywaniu wzorców w języku C#?
Deklaracje i wzorce typów w języku C# sprawdzają, czy typ wykonawczy wyrażenia odpowiada określonemu typowi, i umożliwiają deklarację nowej zmiennej lokalnej w przypadku pomyślnego dopasowania, ułatwiając operacje bezpieczne pod względem typów.
Jak działają wzorce stałych w C#?
Wzorce stałych w C# służą do sprawdzenia, czy wyrażenie jest równe określonej wartości stałej, takiej jak liczba całkowita czy łańcuch znaków, i wykonują określoną logikę, jeśli zostanie znalezione dopasowanie, umożliwiając łatwe porównania wartości stałych.
Jaki jest cel wzorców relacyjnych w C#?
Wzorce relacyjne w C# umożliwiają porównywanie wyrażeń ze stałymi za pomocą operatorów relacyjnych, takich jak <, >, <= i >=. To przydatne przy implementacji zwięzłych sprawdzeń zakresu w kodzie.
Jak można zastosować wzorce logiczne w C#?
Wzorce logiczne w C# łączą inne wzorce za pomocą operatorów logicznych, takich jak and, or i not, co pozwala na tworzenie złożonych warunków dopasowania wzorców, które mogą jednocześnie oceniać wiele kryteriów.
Co to jest wzorzec odrzucenia w C# i kiedy jest używany?
Wzorzec odrzucenia w C#, reprezentowany przez _, pasuje do każdego wyrażenia, w tym null, i jest często używany w sytuacjach, gdy konkretne wartości muszą być zignorowane, na przykład w wyrażeniach switch.
Jak można wykorzystać wzorce właściwości w C#?
Wzorce właściwości w C# pozwalają deweloperom na dopasowanie właściwości lub pól obiektu do zagnieżdżonych wzorców, co umożliwia przeprowadzenie głębszych sprawdzeń struktury obiektu, zachowując jasny i zwięzły kod.




