入れ子になった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();
}
フラグを使用するのはどうですか?
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: ;
}
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();
コントロールを移動する方法を理解しようとするのではなく、ロジックのように見えるコードを記述してください。ロジックが「他のアイテムのいずれかがdoubleとして解析されない場合は処理しない」というロジックの場合、Any述語を使用して他のすべてのアイテムをテストし、それらのいずれかがdoubleとして解析されないかどうかを確認します。ループがないため、手の込んだループ制御は必要ありません。
私はさらに一歩進んでいきたいと思います。クエリのロジックをキャプチャし、クエリを反復します。
var goodItems = from item in items
where !item.OtherItems.Any(otherItem=>otherItem.TryParseDouble() == null))
select item;
foreach(var goodItem in goodItems)
DoStuff(goodItem);
シンプルがベストです...
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
が発生しないようにします。
それを制御する変数が必要であり、あなたが言うように.. 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();
}
スニペットからは明確ではありませんが、otheritems
で解析できない値のみを探す必要がある場合は、LINQを使用できます。
foreach(var item in items)
{
bool shouldISkip = otheritems.Any(otherItem => !double.TryParse(otherItem));
if(shouldISkip) continue;
DoStuff();
}
休憩してください。ステートメントは最も近いループのみを中断するため、breakを発行します。内側のループでは、外側のループの次のアイテムに続く必要があります。