AIDE .NET

Expressions de correspondance de motifs en C# (Comment ça marche pour les développeurs)

Publié mars 26, 2024
Partager:

Introduction

La recherche de motifs en C# est une fonctionnalité puissante qui a été introduite en C# 7.0 et qui a été développée dans les versions suivantes. Il permet aux développeurs d'écrire un code plus concis et plus expressif lorsqu'ils utilisent des instructions conditionnelles, des vérifications de type et la déconstruction d'objets.

Les expressions de correspondance de motifs offrent un moyen souple et intuitif de faire correspondre des valeurs à des motifs et d'exécuter les blocs de code correspondants. Dans cet article, nous allons explorer les subtilités des expressions de correspondance de motifs en C#, y compris la syntaxe, les cas d'utilisation et les exemples de code. À la fin de l'article, nous aborderons également les sujets suivantsBibliothèque de génération de PDF IronPDF deIron Software pour générer un document PDF à la volée dans les applications C#.

Avantages de la correspondance des formes en C# ;

La recherche de motifs dans le code C# présente une pléthore d'avantages :

  • Meilleure lisibilité : La correspondance des motifs simplifie la logique conditionnelle complexe, ce qui rend votre code plus facile à comprendre et à suivre, tant pour vous que pour les autres développeurs.
  • Réduction des lignes de code : En condensant des instructions conditionnelles complexes en motifs concis, le filtrage par motifs permet de rationaliser votre base de code, ce qui se traduit par un nombre réduit de lignes de code et une mise en œuvre plus succincte.
  • Amélioration de la maintenabilité : La clarté offerte par la recherche de motifs facilite la maintenance et le débogage du code. Les modèles étant clairement délimités, il devient plus simple d'identifier et de modifier des blocs logiques spécifiques en fonction des besoins, sans affecter le reste de la base de code.
  • Des algorithmes plus expressifs : La correspondance des motifs permet aux développeurs d'exprimer les algorithmes de manière plus naturelle et intuitive. En alignant les structures de code sur les paradigmes de résolution de problèmes, l'appariement de modèles facilite la création d'algorithmes qui ressemblent étroitement à leurs modèles conceptuels.

Types de correspondance de motifs en C# ;

La correspondance des motifs est prise en charge par les expressions suivantes :

  • est l'expression
  • déclarations de commutation
  • expressions de commutation

    Les motifs suivants peuvent être utilisés pour faire correspondre les constructions :

Modèles de déclaration et de type

Les modèles de déclaration et de type sont des outils essentiels en C# pour vérifier la compatibilité des types d'exécution de l'expression avec des types donnés. Avec les modèles de déclaration, vous pouvez à la fois vérifier la compatibilité et déclarer une nouvelle variable locale. Prenons l'exemple suivant :

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#

Ici, le modèle de déclaration garantit que si l'expression greeting correspond au type string, elle est affectée à la variable message, ce qui permet les opérations ultérieures.

Lorsque l'une des conditions suivantes est remplie, le modèle de déclaration est valable :

  • Le type d'exécution de l'expression est T.
  • Le type d'exécution de l'expression dérive de T, met en œuvre l'interface T ou peut être implicitement converti en T.
  • Le type d'exécution de l'expression est un type de valeur nullable avec le type sous-jacent T.
  • Il existe une conversion de mise en boîte ou de mise hors boîte du type d'exécution de l'expression vers le type T.

    Prenons l'exemple suivant, qui illustre les conditions susmentionnées :

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#

Ici, nullableX correspond au motif car c'est un type de valeur nullable avec le type sous-jacent int, et boxedy correspond car il peut être unboxé en int.

Lorsque vous avez seulement besoin de vérifier le type d'une expression sans déclarer une nouvelle variable, vous pouvez utiliser la fonction discard _, comme le montre l'exemple ci-dessous :

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#

Dans cet extrait, le _ sert d'espace réservé pour toute correspondance de type Véhicule.

Les motifs de déclaration et de type garantissent que les expressions ne sont pas nulles avant la mise en correspondance des motifs. Vous pouvez vérifier la non-nullité à l'aide d'un modèle de constante nullité inversée, comme illustré ci-dessous :

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

Cette négation permet de s'assurer que l'entrée n'est pas nulle avant de poursuivre les opérations.

En exploitant les modèles de déclaration et de type dans votre code C#, vous pouvez améliorer la lisibilité, réduire le nombre de lignes de code et exprimer les algorithmes plus efficacement. Ces modèles fournissent un moyen concis et expressif de gérer la logique basée sur les types et d'améliorer la maintenabilité de votre base de code.

Modèle constant

Les motifs constants permettent de vérifier si le résultat d'une expression correspond à une valeur constante spécifique. Prenons l'exemple suivant :

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#

Ici, les motifs constants vérifient si visitorCount correspond à l'une des valeurs constantes spécifiées et renvoient les prix des billets correspondants.

Dans un modèle constant, vous pouvez utiliser différents types d'expressions constantes, telles que :

  1. Les littéraux numériques entiers ou à virgule flottante.

  2. Personnages.

  3. Chaînes de caractères.

  4. Valeurs booléennes(vrai ou faux).

  5. Valeurs de l'énumération.

  6. Le nom d'un champ const ou local déclaré.

  7. nul.

    Une expression de type Spanou ReadOnlySpanpeut correspondre à des chaînes de caractères constantes.

    Pour vérifier la présence de nullité, utilisez un modèle constant comme suit :

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

Ici, le modèle s'assure que l'entrée est nulle avant de procéder à d'autres opérations.

Vous pouvez également utiliser un modèle de constante null négativé pour vérifier les valeurs non nulles :

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

Ce modèle vérifie que l'entrée n'est pas nulle, ce qui permet d'effectuer les opérations suivantes en toute sécurité.

En incorporant des modèles de constantes dans votre code C#, vous pouvez gérer efficacement les scénarios dans lesquels des valeurs constantes spécifiques doivent être appariées, améliorant ainsi la clarté et la maintenabilité du code.

Modèles relationnels

Les modèles relationnels permettent de comparer les résultats d'une expression avec des constantes. Prenons l'exemple suivant :

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#

Ici, les modèles relationnels comparent la mesure à des seuils spécifiques pour déterminer sa classification.

La partie droite d'un motif relationnel doit être une expression constante, qui peut être de type entier, flottant, char ou enum. Les opérateurs <, >, <=, ou >= peuvent être utilisés du côté gauche.

Pour faire correspondre le résultat d'une expression à l'intérieur d'une certaine plage, utilisez un motif conjonctif et, comme illustré ci-dessous :

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#

Cet extrait décrit comment le motif conjonctif "et" est utilisé pour déterminer la saison calendaire en fonction du mois qui se situe dans des fourchettes spécifiques. Il mentionne également que les modèles relationnels fournissent un moyen concis et expressif de comparer les résultats d'une expression à des constantes, améliorant ainsi la clarté et la maintenabilité du code.

Modèle de rejet

Le motif de rejet, désigné par _, permet de faire correspondre n'importe quelle expression, y compris null. Prenons l'exemple suivant :

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#

Dans le modèle de rejet, l'exemple ci-dessus traite toutes les valeurs d'entrée possibles. Tous les jours de la semaine sont traités et représentent la valeur par défaut. Toutes les valeurs possibles sont ainsi traitées. Le motif de rejet ne peut pas être utilisé comme motif dans une expression is ou une instruction switch. Dans ce cas, vous pouvez utiliser un motif var avec un rejet, comme var _, pour faire correspondre n'importe quelle expression. Toutefois, un motif de rejet est autorisé dans une expression de commutation. Pour plus de détails, veuillez vous référer à la section "Discard pattern" de la note de proposition de fonctionnalité.

Modèles logiques

Les motifs logiques en C# offrent des outils puissants pour la correspondance des motifs, notamment la négation, la conjonction et la disjonction, qui permettent des conditions de correspondance plus souples et plus expressives.

Négation (pas de modèle)

Le motif de négation, représenté par "not", correspond à une expression lorsque le motif nié ne correspond pas à l'expression. Ceci est particulièrement utile pour vérifier si une expression est non nulle, comme démontré ci-dessous :

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

Ici, le bloc de code est exécuté si l'entrée n'est pas nulle.

Conjonctif (et modèle)

Le motif conjonctif, qui utilise le mot-clé "et", correspond à une expression lorsque les deux motifs correspondent à l'expression. Cela permet de combiner plusieurs conditions, comme l'illustre l'exemple suivant :

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#

Dans cet exemple, la mesure est classée en fonction de sa plage de valeurs.

Disjonctive (ou modèle)

Le motif disjonctif, qui utilise le mot-clé "ou", correspond à une expression lorsque l'un ou l'autre des motifs correspond à l'expression. Cela permet de traiter plusieurs conditions possibles, comme indiqué ci-dessous :

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#

Ici, la saison calendaire est déterminée sur la base du mois de la date fournie.

Ces combinateurs de motifs peuvent être utilisés à plusieurs reprises pour créer des conditions de correspondance plus complexes et plus précises, ce qui améliore la flexibilité et la lisibilité de votre code.

Modèle de propriété

Le motif de propriété permet de faire correspondre les propriétés ou les champs d'une expression à des motifs imbriqués. Un exemple de ceci peut être vu dans l'extrait de code suivant :

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#

Ici, le modèle de propriété garantit que la date fournie correspond à l'un des jours de conférence spécifiés.

Vous pouvez également intégrer une vérification de type à l'exécution et une déclaration de variable dans un modèle de propriété, comme indiqué ci-dessous :

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#

Ici, le modèle de propriété est utilisé pour gérer les chaînes de caractères et les collections de caractères, en garantissant un traitement approprié en fonction de leurs propriétés.

Schéma de positionnement

En C#, le motif positionnel permet de déconstruire le résultat d'une expression et de faire correspondre les valeurs résultantes à des motifs imbriqués correspondants. Par exemple :

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#

Dans cet exemple, le modèle de position est utilisé pour classer les points en fonction de leurs coordonnées.

En outre, vous pouvez faire référence à des propriétés ou à des champs imbriqués dans un modèle de propriété, connu sous le nom de modèle de propriété étendu, introduit dans 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
VB   C#

Cette fonctionnalité améliore la flexibilité des modèles de propriétés en permettant un accès direct aux propriétés imbriquées.

Ces modèles fournissent des mécanismes puissants pour gérer des structures de données complexes et améliorer la lisibilité et l'expressivité de votre code.

Modèle Var

Var Pattern vous permet de faire correspondre n'importe quel type. Cela peut être particulièrement utile pour capturer des résultats intermédiaires dans des expressions booléennes ou lorsque des vérifications multiples sont nécessaires dans des gardes de cas de commutation.

Voici un exemple illustrant l'utilisation de var pattern dans une expression booléenne :

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#

Dans cet exemple, SimulateDataFetch renvoie un tableau d'entiers, et le motif is var capture le résultat dans la variable results, permettant des calculs ultérieurs basés sur ses propriétés.

En outre, les motifs var peuvent être utilisés dans des expressions ou des instructions de commutation pour un code plus concis et plus lisible. Voici un exemple d'utilisation du motif var dans les gardes de cas de commutation :

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#

Dans cet exemple, le motif var(x, y) capture les coordonnées du point, permettant ainsi différentes transformations basées sur leurs valeurs.

Dans un motif var, le type de la variable déclarée est déduit du type à la compilation de l'expression correspondant au motif.

Le modèle var offre un moyen pratique de gérer divers scénarios dans lesquels le type spécifique d'expression n'est pas connu à l'avance, ce qui améliore la clarté et la flexibilité du code.

Présentation de la bibliothèque IronPDF

Rendu de documents IronPDF est une bibliothèque d'Iron Software spécialisée dans la génération de documents PDF. Pour commencer, la première chose à faire est d'installer la bibliothèque à partir du gestionnaire de paquets NuGet ou du gestionnaire de paquets Visual Studio

Install-Package IronPdf

L'image ci-dessous montre comment procéder à l'installation à partir deGuide d'installation de Visual Studio.

Expressions de correspondance de motifs en C# (comment cela fonctionne pour les développeurs) : Figure 1 - Installation d'IronPDF avec le gestionnaire de paquets NuGet

Dans le code ci-dessous, nous verrons comment générer un simple document PDF :

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#

Sortie

Expressions de correspondance de motifs en C# (comment cela fonctionne pour les développeurs) : Figure 2

Détails du code

Nous utilisons iciLa classe ChromePdfRenderer d'IronPDF pour enregistrer la chaîne HTML dans un document PDF. Le résultat est enregistré dans le document "output.pdf".

Licence d'essai

IronPDF peut être utilisé avec unlicence d'essai obtenu à partir de laPage de licence IronPDF. Fournissez un identifiant de courrier électronique pour générer une clé de licence qui vous sera envoyée par courrier électronique.

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

Placez la clé de licence dans le fichier AppSettings.Json comme indiqué ci-dessus.

Conclusion

Les expressions de correspondance de motifs en C# offrent un moyen puissant et flexible d'écrire des instructions conditionnelles, des vérifications de type et des déconstructions d'objets de manière concise et lisible. En s'appuyant sur la recherche de motifs, les développeurs peuvent améliorer la clarté et la facilité de maintenance de leur code tout en réduisant les répétitions et les redondances. Qu'il s'agisse de vérification de type, d'instructions de commutation ou de déconstruction, les expressions de correspondance de motifs constituent un ensemble d'outils polyvalents permettant de s'attaquer à un large éventail de tâches de programmation en C#.

En conclusion, la maîtrise des expressions de correspondance de motifs peut grandement améliorer vos compétences en programmation C#, en vous permettant d'écrire un code plus propre et plus expressif, plus facile à comprendre et à maintenir. Nous avons également couvertCapacités de génération de HTML en PDF d'IronPDFla traduction doit rester professionnelle et préserver l'exactitude technique tout en expliquant les caractéristiques et les avantages de ces outils de développement.

< PRÉCÉDENT
.NET Software Development (How It Works For Developers) (Développement de logiciels .NET (Comment cela fonctionne pour les développeurs))
SUIVANT >
C# interne (Comment ça marche pour les développeurs)