Si j'ai une boucle foreach imbriquée, comment puis-je rompre la boucle intérieure et dire à l'extérieur de continuer à ce point sans faire d'autre code en dessous de la boucle intérieure?
foreach(var item in items)
{
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
//break inner loop
//continue outer loop so we never get to DoStuff()
}
}
DoStuff();
}
Que diriez-vous d'utiliser un drapeau?
foreach(var item in items)
{
bool flag = false;
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
flag = true;
break;
}
}
if(flag) continue;
DoStuff();
}
foreach(var item in items)
{
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
//...
goto nextUpperLoop;
}
}
DoStuff();
nextUpperLoop: ;
}
Commencez par écrire une meilleure version de Double.TryParse:
static double? TryParseDouble(this string s)
{
double d;
return double.TryParse(s, out d) ? (double?)d : (double?)null;
}
OK, vous avez maintenant quelque chose que vous pouvez facilement utiliser pour éliminer complètement la boucle intérieure, donc le problème disparaît:
foreach(var item in items)
if (!otheritems.Any(otherItem=>otherItem.TryParseDouble() == null))
DoStuff();
Plutôt que d'essayer de comprendre comment déplacer le contrôle, il suffit d'écrire du code qui ressemble à la logique. Si la logique est "ne faites rien si aucun des autres éléments n'est analysé comme double", utilisez le prédicat Any pour tester tous les autres éléments pour voir si l'un d'eux n'analyse pas en double. Aucune boucle, donc aucun contrôle de boucle sophistiqué n'est nécessaire.
Je serais enclin à aller plus loin; capturer la logique dans une requête, puis itérer la requête:
var goodItems = from item in items
where !item.OtherItems.Any(otherItem=>otherItem.TryParseDouble() == null))
select item;
foreach(var goodItem in goodItems)
DoStuff(goodItem);
La simplicité est la meilleure ...
bool doStuff = true;
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
doStuff = false;
break;
}
}
if(doStuff) DoStuff();
Une autre approche consiste à refactoriser:
foreach(var outerItem in outerLoop) {
Foo(outerItem);
}
...
void Foo(OuterItem item) {
foreach(var innerItem in innerLoop) {
if(someTest) return;
}
DoStuff();
}
return
garantit que DoStuff
ne se produit pas.
Vous avez besoin d'une variable pour contrôler cela et comme vous le dites .. faites un break
.
bool doStuff = true;
foreach(var item in items)
{
doStuff = true;
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
doStuff = false;
break;
}
}
if (doStuff)
DoStuff();
}
foreach(var item in items)
{
var shouldContinue = false;
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
shouldContinue = true;
//break inner loop
//continue outer loop so we never get to DoStuff()
}
}
if(shouldContinue)
continue;
DoStuff();
}
Ce n'est pas clair à partir de votre extrait de code, mais si vous n'avez qu'à rechercher des valeurs non analysables dans otheritems
, vous pouvez utiliser LINQ:
foreach(var item in items)
{
bool shouldISkip = otheritems.Any(otherItem => !double.TryParse(otherItem));
if(shouldISkip) continue;
DoStuff();
}
Iirc une pause; L'instruction rompra uniquement la boucle la plus proche, émettant ainsi une interruption; dans la boucle intérieure doit continuer avec l'élément suivant sur la boucle extérieure.