Continuer dans les boucles nestedes

Dans cet exemple de code, existe-t-il un moyen de continuer sur la boucle externe à partir du bloc catch?

while { // outer loop while { // inner loop try { throw; } catch { // how do I continue on the outer loop from here? continue; } } } 

MISE À JOUR: Cette question a inspiré mon article sur ce sujet. Merci pour la bonne question!


“continue” et “break” ne sont rien de plus qu’une agréable syntaxe pour un “goto”. Apparemment, en leur donnant des noms mignons et en limitant leurs usages à des structures de contrôle particulières, ils ne dessinent plus la colère de la foule «tous les gotos sont toujours mauvais».

Si ce que vous voulez faire, c’est un continuer vers l’extérieur, vous pouvez simplement définir une étiquette en haut de la boucle externe, puis “aller à” cette étiquette. Si vous estimiez que cela ne gênait pas la compréhensibilité du code, cela pourrait être la solution la plus appropriée.

Cependant, je considérerais cela comme une opportunité de considérer si votre stream de contrôle bénéficierait d’une refactorisation. Chaque fois que j’ai des “break” et “continue” conditionnels dans des boucles nestedes, je considère le refactoring.

Considérer:

 successfulCandidate = null; foreach(var candidate in candidates) { foreach(var criterion in criteria) { if (!candidate.Meets(criterion)) // Edited. { // TODO: no point in continuing checking criteria. // TODO: Somehow "continue" outer loop to check next candidate } } successfulCandidate = candidate; break; } if (successfulCandidate != null) // do something 

Deux techniques de refactoring:

D’abord, extrayez la boucle interne à une méthode:

 foreach(var candidate in candidates) { if (MeetsCriteria(candidate, criteria)) { successfulCandidate = candidate; break; } } 

Deuxièmement, toutes les boucles peuvent-elles être éliminées? Si vous faites une boucle parce que vous tentez de rechercher quelque chose, convertissez-le en requête.

 var results = from candidate in candidates where criteria.All(criterion=>candidate.Meets(criterion)) select candidate; var successfulCandidate = results.FirstOrDefault(); if (successfulCandidate != null) { do something with the candidate } 

S’il n’y a pas de boucles, il n’y a pas besoin de casser ou de continuer!

  while { // outer loop while { // inner loop try { throw; } catch { // how do I continue on the outer loop from here? goto REPEAT; } } // end of outer loop REPEAT: // some statement or ; } 

Problème résolu. (quoi ?? Pourquoi vous me donnez tous ce sale look?)

Vous pouvez utiliser une pause; déclaration.

 while { while { try { throw; } catch { break; } } } 

Continuer est utilisé pour revenir en haut de la boucle en cours.

Si vous avez besoin de séparer plus de niveaux, vous devrez soit append une sorte de “if” ou utiliser le “goto” redouté / non recommandé.

Échangez la structure try / catch avec la boucle while interne:

 while { try { while { throw; } } catch { continue; } } 

Non.
Je suggère, extraire la boucle interne dans une méthode distincte.

 while { // outer loop try { myMethodWithWhileLoopThatThrowsException() } catch { // how do I continue on the outer loop from here? continue; } } } 

Utilisez le break dans la boucle interne.

Vous voulez juste sortir de l’intérieur qui continuerait l’extérieur.

 while { // outer loop while { // inner loop try { throw; } catch { // how do I continue on the outer loop from here? break; } } } 

Je pense que la meilleure façon d’y parvenir serait d’utiliser la déclaration de rupture . La rupture met fin à la boucle en cours et continue l’exécution à partir de la fin . Dans ce cas, cela mettrait fin à la boucle interne et retournerait dans la boucle while externe . Voici à quoi ressemblerait votre code:

 while { // outer loop while { // inner loop try { throw; } catch { // break jumps to outer loop, ends inner loop immediately. break; //THIS IS THE BREAK } } } 

Je crois que c’est ce que vous cherchiez à accomplir, correct? Merci!

 using System; namespace Examples { public class Continue : Exception { } public class Break : Exception { } public class NestedLoop { static public void ContinueOnParentLoopLevel() { while(true) try { // outer loop while(true) { // inner loop try { throw new Exception("Bali mu mamata"); } catch (Exception) { // how do I continue on the outer loop from here? throw new Continue(); } } } catch (Continue) { continue; } } } } } 

Utilisez un type d’exception, par exemple, MyException. Alors:

 while { try { // outer loop while { // inner loop try { throw; } catch { // how do I continue on the outer loop from here? throw MyException; } } } catch(MyException) { ; } } 

Cela fonctionnera pour continuer et sortir de plusieurs niveaux de déclarations nestedes. Désolé pour le mauvais formatage;)