Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
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#. Commencez par la vue d’ensemble des critères correspondants si les modèles sont nouveaux pour vous. Pour connaître les règles de langage complètes, consultez les modèles de propriétés et les modèles positionnels dans la référence de langage.
Les modèles de propriété et de position testent les deux parties d’une valeur. La différence est la façon dont elles identifient ces parties :
- Un modèle de propriété nomme les propriétés ou les champs à tester.
- Un modèle positionnel identifie les valeurs par leur ordre.
Une déconstruction expose un ensemble ordonné de valeurs de composant. Un tuple possède déjà un ordre pour ses éléments ; voir la déconstruction de tuples. Pour un autre type, une Deconstruct méthode définit les valeurs de composant exposées et leur ordre.
Comparer les noms et les positions
Le modèle de propriété suivant teste deux propriétés nommées d’une lecture météorologique, avec des valeurs de température en degrés Celsius :
static bool IsHotAndHumid(WeatherReading reading) =>
reading is { TemperatureC: > 30, HumidityPercent: > 70 };
sealed record WeatherReading(int TemperatureC, int HumidityPercent);
Le modèle positionnel suivant teste une valeur de signal suivie d’une valeur booléenne :
static string GetCrossingInstruction(
PedestrianSignal signal, bool crossingIsClear) =>
(signal, crossingIsClear) switch
{
(PedestrianSignal.Walk, true) => "Cross now",
(PedestrianSignal.Walk, false) => "Wait for the crossing to clear",
_ => "Wait for the walk signal"
};
enum PedestrianSignal
{
Stop,
Walk
}
Le modèle de propriété identifie ses entrées par les noms TemperatureC et HumidityPercent. Le code de croisement crée un tuple à partir des valeurs distinctes crossingIsClear et signal. Le modèle tuple identifie ensuite ces valeurs par ordre : signal première et crossingIsClear seconde. Un modèle positionnel convient particulièrement bien, car ce tuple nouvellement créé ne comporte que deux valeurs, et leur ordre a une signification claire dans la décision de croisement.
Choisissez un modèle de propriété lorsque les noms de membres vous aident à expliquer le test. Les modèles de propriété sont généralement plus clairs pour les classes, les structs et les enregistrements. Choisissez un modèle positionnel lorsque l’ordre donne déjà aux valeurs une signification évidente. Les modèles positionnels sont les plus utiles avec des tuples, qui combinent plusieurs valeurs associées en une seule valeur avec un ordre fixe.
Suivre les entrées imbriquées dans des modèles récursifs
Les modèles de propriété et de position sont des modèles récursifs : ils appliquent un autre modèle à chaque propriété, champ ou position qu’ils sélectionnent. La valeur sélectionnée devient l’entrée de ce modèle imbriqué.
Dans IsHotAndHumid, l’expression reading est l’entrée du modèle de propriété. C# évalue cette expression avant d’effectuer la correspondance. Le modèle obtient deux valeurs de l’objet résultant :
- Le modèle
> 30relationnel teste la valeur deTemperatureC. - Le modèle
> 70relationnel teste la valeur deHumidityPercent.
Un test de type externe est facultatif et les clauses de modèle récursives peuvent être vides. Par exemple, le modèle { } de propriété vide correspond à n’importe quelle valeur non null évaluée.
Les motifs de propriété et positionnels correspondent uniquement à des valeurs évaluées non nulles. Quand null il fait partie du domaine d’entrée, choisissez un modèle récursif qui recherche d’abord une valeur non null :
static string DescribeNullableInput(object? value)
{
if (value is not { } nonNullValue)
{
return "No value";
}
return nonNullValue switch
{
DateTime => "Date",
string => "Text",
_ => "Another type"
};
}
L’expression d’entrée est value. C# l’évalue, et le modèle de propriété { } teste si la valeur résultante n’est pas nulle avant de l’affecter à nonNullValue. L’expression switch suivante peut ensuite tester plusieurs types d’exécution possibles. Ses motifs de type string et DateTime n’ont pas de désignation, car la méthode doit seulement identifier chaque type, et non capturer sa valeur.
Lorsque les clauses de modèle récursives contiennent des modèles imbriqués, chaque propriété, champ ou position sélectionné devient l’entrée de son modèle imbriqué.
Vous pouvez ajouter un test de type avant les accolades lorsque l’expression en entrée peut renvoyer différents types. Vous pouvez également utiliser un chemin d’accès de membre pour tester une propriété imbriquée :
static string DescribeDate(object? value) =>
value switch
{
DateTime { Date.DayOfWeek:
DayOfWeek.Saturday or DayOfWeek.Sunday } => "Weekend date",
DateTime => "Weekday date",
null => "No date",
_ => "Not a date"
};
value est l’expression d’entrée. C# l’évalue d’abord et teste si la valeur résultante est un DateTime. La valeur de la propriété Date sert ensuite d’entrée pour l’accès au membre DayOfWeek. Enfin, la DayOfWeek valeur devient l’entrée du modèle logique qui teste deux constantes. La correspondance réussit lorsque la valeur extérieure a le type spécifié et que chaque objet nécessaire sur le chemin d’accès au membre n’est pas nul.
Comparer des modèles avec des instructions de branchement
La méthode précédente DescribeDate exprime quatre résultats sous forme de modèles :
static string DescribeDate(object? value) =>
value switch
{
DateTime { Date.DayOfWeek:
DayOfWeek.Saturday or DayOfWeek.Sunday } => "Weekend date",
DateTime => "Weekday date",
null => "No date",
_ => "Not a date"
};
La méthode suivante produit les mêmes résultats avec une série d’instructions de branchement impératives :
static string DescribeDateWithBranches(object? value)
{
if (value is DateTime date)
{
if (date.DayOfWeek == DayOfWeek.Saturday ||
date.DayOfWeek == DayOfWeek.Sunday)
{
return "Weekend date";
}
return "Weekday date";
}
if (value is null)
{
return "No date";
}
return "Not a date";
}
La version basée sur un modèle conserve les résultats possibles quand plusieurs branches testent le type et la forme d’une valeur. La version impérative rend chaque test et étape de retour explicite. Dans un cas, l’une ou l’autre forme peuvent sembler similaires. À mesure que le nombre de branches associées augmente, les modèles peuvent faciliter la comparaison des alternatives.