Instructions de sélection

Références

L'actualité

Librairie

L'information

Introduction

Une instruction de sélection entraîne le transfert du contrôle du programme vers un flux spécifique selon qu'une certaine condition est true ou false. Les mots clés suivants sont utilisés dans les instructions de sélection :

  • if
  • else
  • switch
  • case
  • default

if-else

Une instruction if identifie l'instruction à exécuter en fonction de la valeur d'une expression booléenne. Dans l'exemple suivant, la variable bool condition est définie sur true puis archivé dans l'instruction if. Le résultat est "The variable is set to true".

En C#, une instruction if peut prendre deux formes, comme le montre l'exemple suivant.

Dans une instruction if-else, si la condition a la valeur true, then-statement s'exécute. Si la condition a la valeur false, else-statement s'exécute. Sachant que condition ne peut pas avoir simultanément les valeurs true et false, then-statement et else-statement d'une instruction if-else ne peuvent jamais s'exécuter. Une fois que then-statement ou else-statement s'est exécuté, le contrôle est transféré à l'instruction suivante après l'instruction if.

Dans une instruction if qui n'inclut pas d'instruction else, si la condition a la valeur true, then-statement s'exécute. Si la condition a la valeur false, le contrôle est transféré à l'instruction suivante après l'instruction if.

then-statement et else-statement peuvent tous deux être constitués d'une ou plusieurs instructions placées entre accolades ({}). Pour une seule instruction, les accolades sont facultatives, mais recommandées.

La ou les instructions contenues dans then-statement et else-statement peuvent être de n'importe quel type, y compris une autre instruction if imbriquée à l'intérieur de l'instruction if d'origine. Dans les instructions if imbriquées, chaque clause else appartient à la dernière instruction if qui n'a pas d'instruction else correspondante. Dans l'exemple suivant, Result1 s'affiche si m > 10 et n > 20 ont tous deux la valeur true. Si m > 10 a la valeur true, mais que n > 20 a la valeur false, Result2 s'affiche.

Si vous préférez que Result2 s'affiche quand (m > 10) a la valeur false, vous pouvez spécifier cette association au moyen d'accolades pour établir le début et la fin de l'instruction if imbriquée, comme le montre l'exemple suivant.

Result2 s'affiche si la condition (m > 10) a la valeur false.

Exemple

Dans l'exemple suivant, vous entrez un caractère au clavier et le programme utilise une instruction if imbriquée pour déterminer si le caractère d'entrée est un caractère alphabétique. Si le caractère d'entrée est un caractère alphabétique, le programme vérifie si c'est une minuscule ou une majuscule. Un message s'affiche dans chaque cas.

Vous pouvez aussi imbriquer une instruction if à l'intérieur d'un bloc else, comme le montre l'extrait de code suivant. L'exemple imbrique des instructions if à l'intérieur de deux blocs else et d'un bloc then. Les commentaires précisent les conditions qui sont vraies (true) et celles qui sont fausses (false) dans chaque bloc.

L'exemple suivant détermine si un caractère d'entrée est une lettre minuscule, une lettre majuscule ou un nombre. Si ces trois conditions ont la valeur false, le caractère n'est pas un caractère alphanumérique. L'exemple affiche un message dans chaque cas.

De la même manière que le bloc else ou le bloc then peuvent contenir n'importe quelle instruction valide, vous pouvez utiliser n'importe quelle expression booléenne valide pour la condition. Vous pouvez utiliser des opérateurs logiques tels que &&, &, ||, |, ! pour former des conditions composées. Le code suivant présente des exemples.


switch

switch est une instruction de sélection qui choisit une section de commutation unique à exécuter à partir d'une liste de candidats en fonction d'une mise en correspondance de modèle avec l'expression de correspondance.

L'instruction switch est souvent utilisée comme alternative à une construction if-else si une expression unique est testée en fonction de trois conditions ou plus. Par exemple, l'instruction switch suivante détermine laquelle des trois valeurs possibles a été affectée à une variable de type Color :

Il est équivalent à l'exemple suivant qui utilise une construction if-else.

Expression de correspondance

L'expression de correspondance fournit la valeur à mettre en correspondance avec les modèles dans les étiquettes case. Sa syntaxe est la suivante :

En C# 6, l'expression de correspondance doit être une expression qui retourne une valeur d'un des types suivants :

  • char
  • string
  • bool
  • valeur intégrale, telle que int ou long
  • valeur enum

à compter de C# 7.0, l'expression de correspondance peut être toute expression non Null.

Section de commutation

Une instruction switch inclut une ou plusieurs sections de commutation. Chaque section de commutation contient une ou plusieurs étiquettes case (une case ou une étiquette par defaut) suivies d'une ou de plusieurs instructions. L'instruction switch peut inclure au maximum une étiquette par défaut, placée dans n'importe quelle section de commutation. L'exemple suivant montre une instruction switch simple qui a trois sections de commutation, chacune contenant à son tour deux instructions. La deuxième section de commutation contient les étiquettes case 2: et case 3:.

Une instruction switch peut inclure un nombre quelconque de sections de commutation, et chaque section peut contenir une ou plusieurs étiquettes case, comme dans l'exemple ci-dessous. Toutefois, deux étiquettes case ne doivent pas contenir la même expression.

Une seule section de commutation s'exécute dans une instruction switch. C# ne permet pas à l'exécution de passer d'une section switch à la suivante. Pour cette raison, le code suivant génère une erreur de compilation, CS0163 : "Le contrôle ne peut pas passer d'une étiquette case() à une autre."

Si cela est nécessaire, il est possible de procéder en quittant explicitement la section de commutation à l'aide d'une instruction break, goto ou return. Toutefois, le code suivant est également valide, car il garantit que le contrôle du programme ne peut pas passer à la section de commutation default.

L'exécution de la liste d'instructions dans la section de commutation avec une étiquette case qui correspond à l'expression de correspondance commence avec la première instruction et continue en suivant la liste d'instructions, en général jusqu'à ce qu'une instruction de saut, telle que break, goto case, goto label, return ou throw, soit atteinte. Á ce stade, le contrôle est transféré hors de l'instruction switch ou vers un autre nom de cas. Si une instruction goto est utilisée, elle doit transférer le contrôle à une étiquette constante. Cette restriction est nécessaire, car tenter de transférer le contrôle à une étiquette non constante peut avoir des effets indésirables, tels que le transfert du contrôle à un emplacement inattendu dans le code ou la création d'une boucle sans fin.

Étiquettes case

Chaque étiquette case spécifie un modèle à comparer à l'expression de correspondance (la variable caseSwitch dans les exemples précédents). S'ils correspondent, le contrôle est transféré à la section de commutation qui contient la première étiquette case correspondante. Si aucun modèle d'étiquette case ne correspond à l'expression de correspondance, le contrôle est transféré à la section avec l'étiquette case default, si une telle section existe. En l'absence d'étiquette case default, aucune instruction d'aucune section de commutation n'est exécutée et le contrôle est transféré hors de l'instruction switch.

Étant donné que C# 6 prend en charge uniquement le modèle de constante et n'autorise pas la répétition des valeurs constantes, les étiquettes case définissent des valeurs qui s'excluent mutuellement, et un seul modèle peut correspondre à l'expression de correspondance. Par conséquent, l'ordre dans lequel les instructions case apparaissent n'a pas d'importance.

Dans C# 7.0, toutefois, comme d'autres modèles sont pris en charge, les étiquettes case ne sont pas tenues de définir des valeurs s'excluant mutuellement et plusieurs modèles peuvent correspondre à l'expression de correspondance. Comme seules les instructions de la première section de commutation contenant le modèle correspondant sont exécutées, l'ordre dans lequel les instructions /code>case apparaissent est désormais important. Si C# détecte une section de commutation dont la ou les instructions /code>case sont équivalentes aux instructions précédentes, ou en sont des sous-ensembles, C# génère une erreur du compilateur, CS8120, "Le switch case a déjà été pris en charge par un case antérieur".

L'exemple suivant illustre une instruction switch qui utilise divers modèles ne s'excluant pas mutuellement. Si vous déplacez la section de commutation case 0: pour qu'elle ne soit plus la première section dans l'instruction switch, C# génère une erreur du compilateur, car un entier dont la valeur est égale à zéro est un sous-ensemble de tous les entiers, ce qui est le modèle défini par l'instruction case int val.

Vous pouvez corriger ce problème et éliminer l'avertissement du compilateur de deux façons :

  • en modifiant l'ordre des sections de commutation ;
  • en utilisant une clause when dans l'étiquette case.
Étiquette case default

L'étiquette case default spécifie la section de commutation à exécuter si l'expression de correspondance ne correspond à aucune autre étiquette case. En l'absence d'une étiquette case default, si l'expression de correspondance ne correspond à aucune autre étiquette case, le flux de programme traverse l'instruction switch.

L'étiquette case default peut apparaître à n'importe quelle position dans l'instruction switch. Quelle que soit sa position dans le code source, elle est toujours évaluée en dernier, une fois que toutes les étiquettes case ont été évaluées.

Critères spéciaux avec l'instruction switch

Chaque instruction case définit un modèle qui, s'il correspond à l'expression de correspondance, entraîne l'exécution de la section de commutation qui le contient. Toutes les versions de C# prennent en charge le modèle de constante. Les autres modèles sont pris en charge à compter de C# 7.0.

Modèle de constante

Le modèle de constante teste si l'expression de correspondance est égale à une constante spécifiée. Sa syntaxe est la suivante :

Où constant est la valeur à tester. constant peut être l'une quelconque des expressions constantes suivantes :

  • Un littéral de valeur booléenne, true ou false
  • Toute constante intégrale, de type int, long ou byte
  • Le nom d'une variable const déclarée
  • Une constante d'énumération
  • Un littéral de type char
  • Un littéral de type string
L'expression constante est évaluée de la manière suivante :

  • Si expr et constant sont des types intégraux, l'opérateur d'égalité C# détermine si l'expression retourne true (autrement dit, si expr == constant).
  • Sinon, la valeur de l'expression est déterminée par un appel à la méthode statique Object.Equals(expr, constant).

L'exemple suivant utilise le modèle de constante pour déterminer si une date particulière correspond à un jour de week-end, au premier jour de la semaine, au dernier jour de la semaine de travail ou au milieu de la semaine de travail. Il évalue la propriété DateTime.DayOfWeek du jour actuel par rapport aux membres de l'énumération DayOfWeek.

L'exemple suivant utilise le modèle de constante pour gérer l'entrée d'utilisateur dans une application console qui simule une machine à café automatique.

Modèle de type

Le modèle de type permet une évaluation et une conversion rapides de type. Lorsqu'il est utilisé avec l'instruction switch pour effectuer une mise en correspondance de modèle, il permet de tester si une expression peut être convertie en un type spécifié et, si tel est le cas, il effectue un cast de l'expression en une variable de ce type. Sa syntaxe est la suivante :

Où type est le nom du type vers lequel le résultat de expr doit être converti, et varname est l'objet vers lequel le résultat de expr est converti si la correspondance est établie.

L'expression case est true si l'une quelconque des affirmations suivantes est vraie :

  • expr est une instance du même type que type.
  • expr est une instance d'un type qui dérive de type. En d'autres termes, le résultat de expr peut être upcasté en une instance de type.
  • expr a un type au moment de la compilation qui est une classe de base de type et expr a un type au moment de l'exécution égal à type ou dérivé de type. Le type au moment de la compilation d'une variable est le type de la variable, tel qu'il est défini dans sa déclaration de type. Le type au moment de l'exécution d'une variable est le type de l'instance qui est assignée à cette variable.
  • expr est une instance d'un type qui implémente l'interface type.

Si l'expression case est true, varname est définitivement assigné et a une portée locale au sein de la section de commutation uniquement.

Notez que null ne correspond pas à un type. Pour mettre en correspondance null, vous utilisez l'étiquette case suivante :

L'exemple suivant utilise le modèle de type pour fournir des informations sur différentes sortes de types de collection.

Sans critères spéciaux, ce code peut être écrit comme suit. L'utilisation de critères spéciaux de type génère un code plus compact et lisible en éliminant la nécessité de tester si le résultat d'une conversion est un null et d'effectuer des casts répétés.

L'instruction case et la clause when

À compter de C# 7.0, comme les instructions case ne s'excluent pas nécessairement mutuellement, vous pouvez ajouter une clause when pour spécifier une condition supplémentaire qui doit être satisfaite pour que l'instruction case soit évaluée à true. La clause when peut être toute expression qui retourne une valeur booléenne.

L'exemple suivant définit une classe Shape de base, une classe Rectangle qui dérive de Shape et une classe Square qui dérive de Rectangle. Il utilise la clause when pour garantir que le ShowShapeInfo traite un objet Rectangle qui s'est vu assigner des longueurs et des largeurs égales comme celles d'un objet Square même s'il n'a pas été instancié comme objet Square. La méthode ne tente pas d'afficher des informations sur un objet null ou sur une forme dont l'aire est nulle.

Notez que la clause when dans l'exemple qui tente de tester si un objet Shape est null ne s'exécute pas. Le modèle de type correct à utiliser pour tester un null est case null:.