Vue d’ensemble des critères spéciaux

Tip

Cet article fait partie de la section Notions de base pour les développeurs qui connaissent déjà au moins un langage de programmation et apprennent C#. Si vous débutez avec la programmation, commencez par commencer par les didacticiels De prise en main . Les développeurs C# expérimentés peuvent utiliser les modèles de référence pour la syntaxe et les règles complètes .

Venant d’une autre langue ? Les motifs en C# jouent un rôle similaire au filtrage par motif de Java et aux cas match de Python. C# utilise des modèles dans is les expressions, switch les instructions et switch les expressions.

La correspondance de modèle applique un modèle à une expression. Un modèle est une condition pour tester l’expression d’entrée. L’entrée de modèle est cette expression. C# évalue l’expression d’entrée ; le résultat est la valeur évaluée. Le modèle teste si cette valeur a un type particulier, est égale à une valeur particulière ou a une forme particulière. Lorsqu’un modèle correspond, votre code peut utiliser des informations apprises par le test, telles qu’un type plus spécifique ou une valeur extraite d’un objet.

Vous pouvez utiliser un modèle dans trois contextes :

  • À droite de l’opérateur is.
  • Dans une case étiquette d’une switch instruction.
  • Dans une branche d’expression switch.

Les modèles sont souvent plus clairs qu’une séquence d’instructions de comparaison, car chaque branche décrit les données qu’elle gère. Par exemple, la méthode suivante utilise une switch expression pour choisir un message de remise :

static string GetDeliveryMessage(Delivery? delivery) =>
    delivery switch
    {
        null => "No delivery was scheduled.",
        ExpressDelivery express => $"Express package {express.TrackingCode}",
        StandardDelivery { Days: <= 2 } => "Standard delivery arriving soon",
        _ => "Standard delivery"
    };

Les modèles récursifs ont leurs propres expressions d’entrée. Dans StandardDelivery { Days: <= 2 }, le modèle externe reçoit l’expression delivery . Le modèle récursif <= 2 reçoit l’expression Days de propriété de l’objet correspondant StandardDelivery .

L’expression avant switch est l’expression d’entrée. Chaque ligne entre accolades est une branche de commutateur. Le modèle s’affiche avant =>, et le résultat s’affiche après lui. C# évalue l’expression d’entrée, puis sélectionne le premier bras, dans l’ordre de texte, dont le modèle correspond et dont la protection facultative when est true. La protection facultative when est une condition booléenne supplémentaire écrite après le modèle. L’exemple précédent montre les modèles suivants :

  • null est un modèle constant. Teste si l’expression delivery est évaluée à null.
  • ExpressDelivery express est un modèle de déclaration avec deux parties. ExpressDelivery est la partie de test de type. Elle teste si la valeur évaluée est un objet non null dont le type d’exécution est compatible avec ExpressDelivery. express est la désignation de variable : elle déclare une variable nommée express et lui affecte l’objet correspondant ExpressDelivery .
  • StandardDelivery { Days: <= 2 } commence par un test de type. StandardDelivery teste si la valeur évaluée est un objet non null de ce type. Les accolades contiennent un modèle de propriété. Days nomme la propriété à inspecter, de sorte que l’expression Days de propriété devient l’entrée du modèle récursif. La <= 2 partie est un modèle relationnel, qui teste si la valeur évaluée est inférieure ou égale à 2.
  • _ (trait de soulignement) est le modèle d’abandon. Elle correspond à chaque valeur évaluée, y compris null. Étant donné que les branches précédentes gèrent déjà null, les livraisons express et les livraisons standard arrivant sous deux jours, cette dernière branche gère toutes les autres valeurs.

Un bras sans when garde n’est pas protégé. Tous les bras dans le premier exemple ne sont pas gardés. Si une branche antérieure non gardée correspond à toutes les valeurs évaluées auxquelles une branche ultérieure pourrait correspondre, alors la branche ultérieure est masquée. Un modèle sous-énuméré est un modèle dans lequel chaque valeur d’entrée possible qui correspond a déjà été mise en correspondance par un bras de commutateur antérieur. Il ne peut jamais correspondre, de sorte que le compilateur signale une erreur. Le bras d’abandon (_) doit venir en dernier, car il correspond à chaque expression d’entrée. Un bras gardé ne subsume pas un bras plus tard en fonction de son modèle seul, car le garde peut être false.

Une expression de commutateur est exhaustive lorsque ses bras gèrent chaque expression d’entrée possible. Le premier exemple est exhaustif, car son dernier bras de rejet traite tous les cas que les bras précédents ne couvrent pas. Le compilateur avertit lorsqu’il détecte une valeur d’entrée potentielle qu’aucune branche ne prend en charge. Le compilateur ne peut pas prouver l’exhaustivité de chaque combinaison de modèles, mais ce diagnostic vous aide à écrire du code de correspondance de modèle correct. Pour obtenir des règles détaillées de correspondance, de sous-énumération et d’exhaustivité, consultez la référence des modèles.

Tester une condition avec is

Utilisez l’opérateur is quand vous avez besoin d’un test booléen. Le code suivant évalue l’expression delivery et applique le modèle ExpressDelivery expressde déclaration. La partie type correspond lorsque la valeur évaluée n’est pas null et que son type d’exécution est compatible avec ExpressDelivery. Lorsque le modèle correspond, sa désignation de variable déclare express:

static void PrintTrackingCode(Delivery delivery)
{
    if (delivery is ExpressDelivery express)
    {
        Console.WriteLine($"Track express package {express.TrackingCode}");
    }
}

Le compilateur suit si une variable locale a été affectée avant que votre code ne le lise. Ce suivi est appelé affectation définitive. Dans le bloc if, la condition n’est true que lorsque le modèle a attribué l’objet correspondant à express. Le compilateur sait donc que express a bien reçu une valeur à cet endroit. Votre code peut utiliser sa TrackingCode propriété en toute sécurité. Vous n’avez pas besoin d’un cast distinct. Si vous avez uniquement besoin du test de type et n’avez pas besoin de déclarer une variable, utilisez un modèle de type, tel que delivery is ExpressDelivery.

Utilisez is null ou is not null pour les vérifications de nullité. Ces modèles n’appellent pas d’opérateur != ou == défini par l’utilisateur.

static void PrintPackageStatus(Delivery? delivery)
{
    if (delivery is null)
    {
        Console.WriteLine("No package is available.");
    }
    else
    {
        Console.WriteLine("A package is ready to track.");
    }
}

Pour obtenir des conseils supplémentaires sur la sécurité relative aux valeurs Null, consultez les types de référence nullables.

Choisir entre une instruction et une expression

Les modèles fonctionnent avec les deux formes de switch:

  • Utilisez une switch instruction lorsque chaque correspondance doit exécuter une ou plusieurs instructions.
  • Utilisez une switch expression lorsque chaque correspondance doit produire une valeur.

L’instruction switch suivante signale une mise à jour de livraison. La branche de livraison express écrit deux messages, donc une instruction s’y intègre naturellement :

static void PrintDeliveryUpdate(Delivery? delivery)
{
    switch (delivery)
    {
        case null:
            Console.WriteLine("No delivery was scheduled.");
            break;
        case ExpressDelivery express:
            Console.WriteLine($"Express delivery {express.TrackingCode} is ready.");
            Console.WriteLine("Notify the priority desk.");
            break;
        case StandardDelivery standard:
            Console.WriteLine($"Standard delivery arrives in {standard.Days} days.");
            break;
        default:
            Console.WriteLine("Another delivery type is scheduled.");
            break;
    }
}

Chacun case applique un modèle à l’expression delivery . La section correspondante peut exécuter n’importe quel nombre d’instructions avant break de quitter le commutateur. La section default traite tout ce qui ne correspond à aucun des cas précédents.

L’expression switch suivante remplace une if / else if chaîne qui affecte un résultat :

static string GetStatusMessage(StandardDelivery delivery) =>
    delivery.Days switch
    {
        0 => "Delivered today",
        1 => "Arriving tomorrow",
        <= 3 => "Arriving soon",
        _ => "In transit"
    };

Une expression switch est concise, car chaque bras a le même objectif : produire la valeur retournée. Utilisez une instruction switch lorsque les branches effectuent des actions et utilisez une expression de commutateur lorsque les branches calculent un résultat.

Catégories de modèles

C# inclut des modèles pour les types courants de tests de données :

Catégorie de modèle Ce qu’il teste
Déclaration, constante et var modèles Type d’exécution, valeur constante spécifique ou valeur que vous souhaitez capturer
Modèles de type Type d’exécution sans déclarer de variable
Modèles de propriété et de position Propriétés, champs ou valeurs déconstructées
Modèles relationnels et logiques Comparaisons et combinaisons telles que and, oret not
Modèles de liste Valeurs et forme d’une liste ou d’un tableau
Motifs d’exclusion et éléments exclus Toute valeur restante ou valeur que votre code ignore intentionnellement

Les articles fondamentaux liés dans le tableau fournissent une couverture ciblée des catégories actuellement documentées dans cette section. Pour obtenir une syntaxe complète et des exemples pour toutes les catégories de modèles, consultez la référence des modèles.

Voir aussi