Menu

break, continue et goto en C# : sortir des boucles et des boucles imbriquées

Comment fonctionnent break, continue et goto en C# : terminer une boucle plus tôt, sauter une itération, break dans un switch, trois façons de sortir de boucles imbriquées (un indicateur, goto ou une méthode avec return), et le bug de boucle infinie de continue dans un while.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

break termine une boucle plus tôt. continue saute le reste de l'itération en cours et passe à la suivante. Les deux s'appliquent à la boucle englobante la plus interne, et fonctionnent de la même façon dans for, foreach, while et do while.

Sortie :

process order of 45
skip invalid total 0
process order of 120
skip invalid total -5
process order of 80
test order found, stopping
after the loop

continue a sauté la ligne de traitement pour 0 et -5. break a arrêté la boucle à 999, donc 60 n'a jamais été visité, et l'exécution a repris à la première instruction après la boucle.

break : s'arrêter quand la réponse est connue

L'usage typique de break est une recherche : une fois que vous avez trouvé ce que vous cherchiez, il n'y a aucune raison d'examiner le reste.

Sortie :

first invalid email at index 1

L'itérateur (i++) ne s'exécute pas après un break, donc i contiendrait encore l'index trouvé s'il était déclaré en dehors de la boucle. Pour les recherches simples, un appel de bibliothèque dit la même chose : Array.FindIndex(emails, e => !e.Contains("@")) renvoie l'index (ou -1), et le emails.Any(e => !e.Contains("@")) de LINQ indique s'il en existe un invalide.

continue : passer à l'itération suivante

continue est une clause de garde pour les boucles. Au lieu d'envelopper le vrai travail dans un if, rejetez en haut les cas dont vous ne voulez pas :

Sortie :

pen costs 1.20
mug costs 8.00

L'endroit où continue mène dépend de la boucle. Dans une boucle for, il exécute l'itérateur puis teste la condition. Dans une boucle while, il saute directement à la condition, ce qui mène à un bug classique :

int i = 0;
while (i < 10)
{
    if (i % 2 == 0)
        continue;        // i++ below is skipped: i stays 0 forever
    Console.WriteLine(i);
    i++;
}

Mettez à jour le compteur avant tout continue, ou utilisez une boucle for, où la mise à jour se trouve dans l'en-tête et s'exécute toujours.

break dans un switch dans une boucle

Dans un switch, break termine la section du case. Quand ce switch se trouve dans une boucle, le break appartient au switch, pas à la boucle :

Sortie :

quit received
count = 2

Un simple break dans le cas "quit" n'aurait terminé que le switch, la boucle aurait continué, et count vaudrait 3. Le goto saute à l'étiquette placée après la boucle. Déplacer la boucle dans une méthode et écrire return dans ce cas fonctionne aussi et ne demande pas d'étiquette.

Sortir de boucles imbriquées

C# n'a pas de break étiqueté comme le break outer; de Java. Quand une recherche parcourt deux boucles imbriquées, un break dans la boucle interne ne termine que celle-ci ; la boucle externe passe à sa ligne suivante. Il existe trois corrections standard.

1. Un indicateur que la boucle externe vérifie :

Sortie :

first free seat: row 1, seat 2

2. goto vers une étiquette après les deux boucles. C'est le seul endroit où beaucoup de guides de style C# acceptent goto, car il exprime exactement « quitter les deux boucles » :

for (int row = 0; row < rows; row++)
{
    for (int col = 0; col < cols; col++)
    {
        if (seats[row, col] == 0)
        {
            Console.WriteLine($"first free seat: row {row}, seat {col}");
            goto done;
        }
    }
}
done:
Console.WriteLine("search finished");

3. Une méthode avec return, en général la solution la plus propre, car la recherche reçoit un nom et peut renvoyer son résultat :

Sortie :

first free seat: row 1, seat 2

C# 7.0 a aussi introduit les fonctions locales, qui permettent de placer cette méthode auxiliaire à l'intérieur de la méthode appelante. Le schéma avec paramètres out utilisé ici est expliqué sur la page ref et out.

goto et les étiquettes

Une étiquette est un identifiant suivi de deux-points, et goto label; y saute. Les règles sont assez strictes pour empêcher les pires abus :

  • L'étiquette doit se trouver dans la même méthode, dans le même bloc que le goto ou dans un bloc englobant. Vous pouvez sauter hors d'un bloc mais jamais dans un bloc : sauter depuis l'extérieur vers une étiquette située dans le corps d'une boucle donne l'erreur CS0159 (no such label within the scope of the goto statement).
  • Vous ne pouvez pas quitter un bloc finally avec goto, break ou continue.
  • Dans un switch, goto case 3; et goto default; transfèrent le contrôle vers une autre section. C'est ainsi qu'un switch C# exprime l'enchaînement des cas, puisque glisser implicitement dans le cas suivant est une erreur de compilation.

goto permet aussi de construire des boucles (en sautant en arrière vers une étiquette), mais une boucle while dit la même chose sous une forme que tout lecteur reconnaît. Réservez goto à la sortie de boucles imbriquées et aux sections de switch.

return, throw et les boucles

return quitte toute la méthode, donc aussi toutes les boucles qu'elle contient. throw fait de même en levant une exception. Dans un bloc try doté d'un finally, break, continue, goto et return exécutent tous le bloc finally avant que le contrôle ne passe ailleurs, ce qui permet de sortir sans risque d'une boucle qui garde un fichier ouvert dans un bloc using.

InstructionQuitteReprend à
continuel'itération en coursl'itération suivante (itérateur, puis condition)
breakla boucle ou le switch le plus internel'instruction qui suit
goto labeltous les blocs englobantsl'étiquette
returnla méthodel'appelant
throwtout jusqu'au catch correspondantle bloc catch

Questions fréquentes

Quelle est la différence entre break et continue en C# ?

break termine immédiatement la boucle (ou le switch) la plus interne ; l'exécution reprend après elle. continue ne termine que l'itération en cours et passe à la suivante : dans une boucle for, l'itérateur s'exécute ensuite, dans while et do while la condition est testée ensuite, dans foreach l'élément suivant est récupéré.

Comment sortir de boucles imbriquées en C# ?

C# n'a pas de break étiqueté. Les trois options sont : positionner un indicateur bool et le tester dans la boucle externe, sauter après les deux boucles avec goto vers une étiquette, ou déplacer les boucles dans une méthode et en sortir avec return. La version méthode est en général la plus propre, car elle donne aussi à la recherche un nom et une valeur de retour.

break dans un switch quitte-t-il la boucle en C# ?

Non. Dans un switch placé dans une boucle, break termine la section du switch et la boucle continue. Pour quitter la boucle depuis un case, utilisez return, un indicateur testé après le switch, ou goto vers une étiquette après la boucle. continue dans un case passe bien à l'itération suivante de la boucle.

goto est-il autorisé en C# ?

Oui. goto label; saute à label: dans la même méthode, mais il ne peut pas sauter à l'intérieur d'un bloc ni sortir d'un finally. Dans un switch, goto case value; et goto default; sautent d'une section à l'autre. En dehors de la sortie de boucles imbriquées et de l'enchaînement explicite des cas d'un switch, goto est rarement le choix le plus clair.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER