Разрыв внутренней петли foreach и продолжение внешней петли foreach
Если у меня есть вложенный цикл foreach, как я могу разбить внутренний цикл и сказать внешнему продолжить в этой точке, не делая никакого другого кода ниже внутреннего цикла?
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();
}
Ответы
Ответ 1
Как насчет использования флага?
foreach(var item in items)
{
bool flag = false;
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
flag = true;
break;
}
}
if(flag) continue;
DoStuff();
}
Ответ 2
Начните с написания лучшей версии Double.TryParse:
static double? TryParseDouble(this string s)
{
double d;
return double.TryParse(s, out d) ? (double?)d : (double?)null;
}
ОК, теперь у вас есть что-то, что вы можете легко использовать, чтобы полностью исключить внутренний цикл, поэтому проблема исчезает:
foreach(var item in items)
if (!otheritems.Any(otherItem=>otherItem.TryParseDouble() == null))
DoStuff();
Вместо того, чтобы пытаться выяснить, как перемещать управление, просто напишите код, похожий на логику. Если логика "не делает ничего, если какой-либо из других элементов не анализирует как удваивает", то используйте предикат Any, чтобы проверить все остальные элементы, чтобы увидеть, если какой-либо из них не анализируется как удваивается. Нет циклов, поэтому не требуется никакого элемента управления контурами.
Я был бы склонен идти дальше; захватить логику в запросе и затем повторить запрос:
var goodItems = from item in items
where !item.OtherItems.Any(otherItem=>otherItem.TryParseDouble() == null))
select item;
foreach(var goodItem in goodItems)
DoStuff(goodItem);
Ответ 3
foreach(var item in items)
{
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
//...
goto nextUpperLoop;
}
}
DoStuff();
nextUpperLoop: ;
}
Ответ 4
Простой лучше...
bool doStuff = true;
foreach(var otheritem in otheritems)
{
if (!double.TryParse(otheritem))
{
doStuff = false;
break;
}
}
if(doStuff) DoStuff();
Другой подход - рефакторинг:
foreach(var outerItem in outerLoop) {
Foo(outerItem);
}
...
void Foo(OuterItem item) {
foreach(var innerItem in innerLoop) {
if(someTest) return;
}
DoStuff();
}
return
гарантирует, что DoStuff
не будет.
Ответ 5
Вам нужна переменная для управления этим и, как вы говорите, выполните .
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();
}
Ответ 6
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();
}
Ответ 7
Оператор Iirc a break; будет только разбивать ближайший цикл, поэтому выдача break; во внутреннем цикле должна продолжаться со следующим элементом во внешнем цикле.
Ответ 8
Это не ясно из вашего фрагмента, но если вам нужно искать непараметрируемые значения в otheritems
, то вы можете использовать LINQ:
foreach(var item in items)
{
bool shouldISkip = otheritems.Any(otherItem => !double.TryParse(otherItem));
if(shouldISkip) continue;
DoStuff();
}