更新: この質問は、この主題に関する私の記事のインスピレーションでした。素晴らしい質問をありがとう!
「continue」と「break」は、「goto」の快適な構文にすぎません。どうやら、それらにかわいい名前を付けて、特定の制御構造への使用を制限することで、「すべての goto は常にすべて悪い」群衆の怒りをもはや引き付けません。
やりたいことが外側への継続である場合は、外側のループの上部にラベルを定義してから、そのラベルに「移動」するだけです。そうしてもコードの理解が妨げられないと思われる場合は、それが最も適切な解決策かもしれません。
ただし、これを機会として、制御フローがリファクタリングの恩恵を受けるかどうかを検討します。ネストされたループに条件付きの「中断」と「継続」があるときはいつでも、リファクタリングを検討します。
検討:
successfulCandidate = null;
foreach(var candidate in candidates)
{
foreach(var criterion in criteria)
{
if (!candidate.Meets(criterion))
{ // TODO: no point in continuing checking criteria.
// TODO: Somehow "continue" outer loop to check next candidate
}
}
successfulCandidate = candidate;
break;
}
if (successfulCandidate != null) // do something
2 つのリファクタリング手法:
まず、内側のループをメソッドに抽出します。
foreach(var candidate in candidates)
{
if (MeetsCriteria(candidate, criteria))
{
successfulCandidate = candidate;
break;
}
}
第二に、すべてのループを排除できるか? 何かを検索しようとしてループしている場合は、それをクエリにリファクタリングします。
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
}
ループがない場合は、中断または続行する必要はありません。