C、C++、およびC#では、関数またはループステートメント内で条件を使用する場合、continueまたはreturnステートメントをできるだけ早く使用して、-を取り除くことができます。 elseif-elseステートメントのブランチ。例えば:
while( loopCondition ) {
if( innerCondition ) {
//do some stuff
} else {
//do other stuff
}
}
になります
while( loopCondition ) {
if( innerCondition ) {
//do some stuff
continue;
}
//do other stuff
}
そして
void function() {
if( condition ) {
//do some stuff
} else {
//do other stuff
}
}
になります
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
「after」バリアントは、if-elseブランチが長い場合、この変更によりelseブランチのインデントがなくなるため、読みやすくなる可能性があります。
そのような返品/継続の使用は良い考えですか?メンテナンスや読みやすさの問題はありますか?
コンパイラはほぼ確実に同じコードを生成します。そうでない場合でも、違いはおそらく無関係です。したがって、関連する議論は確かに人々がそれをどのように読むかです。
したがって、問題は「//何かをする」と「他のことをする」がどれほど似ているかということです。概念的に類似している場合は、if/elseを使用します。概念的に異なる場合は、continue/returnを使用してください。
いずれかを選択する私の個人的なアプローチは、if
部分の本体が非常に短い場合(最大3行または4行)、return/continue
バリアントを使用するのが理にかなっているというものです。本体が長いと、制御フローを追跡するのが難しくなるため、else
バージョンを選択します。
その結果、通常、このアプローチでは、return/continue
スタイルの使用が次のいずれかの方法を使用してこれを処理するではなく一部のデータをスキップしてそれ以上の処理を回避するに制限されます。 (これはif/else
に適しています)。
それは枝の長さに少し依存します。最初のif
チェックが短く、本文が長い場合は、説明するreturn/continueの使用が適切です。 if
とelse
の両方の部分が長い場合は、それらを抽出して別々の関数にします。
私はCodeCompleteを読むことをお勧めします、それはこのようなことをたくさん議論します。
終了基準を最初に処理すると、コードが読みやすくなります。私はいつも、長いコード実行を必要とする条件よりも、ブレークまたはリターンを必要とする条件をチェックすることを好みます。私が好む:
if (termination condn)
return;
// code
// code
に
if (success condn)
{
// code
// code
}
else
return;
これにより、コードの読み取りと理解が容易になります。
Glibの答えは、それはすべて依存するということです。
私の一般的な感覚は、condition
がまれな、ガード(nullのチェックなど)またはエラー状態である場合、return
またはcontinue
を使用する傾向があるということです。
それが予想されるケースである場合、私はあなたの最初のアプローチを使用する傾向があります。
ただし、「傾向がある」と言ったことに注意してください。これらと条件の境界はあいまいであり、プロジェクトや私が誰と協力しているかによって変更される可能性があります。
私は通常好きです
while( loopCondition ) {
if( innerCondition ) {
DoStuff();
} else {
DoOtherStuff();
}
}
doStuffの長さが1〜2行のしきい値を超えた場合、続行するのは難しい場合があります(そして、意図を見逃しがちです)。これは、ロジックをいくつかの小さなメソッドにリファクタリングする良い機会のようです。
時期尚早の最適化のために読みやすさを犠牲にしないでください。
例えば:
void function() {
if( condition ) {
//do some stuff
} else {
//do other stuff
}
}
ほとんどの場合、バイナリは同等です
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
(つまり、結果のコードはおそらく同じです)。ただし、コードがXまたはYのいずれかになることがはっきりとわかるため、前者の可読性ははるかに優れています。
1)入力またはオブジェクトの状態の検証。次のコード:
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
条件が機能が機能するための何らかの要件である場合に適しています。これは、入力検証またはオブジェクト状態検証の段階です。その場合、すぐにreturnを使用して強調するのが正しいと感じます。その関数は、まったく実行されませんでした。
2)多段処理。ループがコレクションから要素をポップし、それらを多段階で処理する場合、while/continueは適切です。
while(foo = bar.getNext()) {
if(foo.empty())
continue;
if(foo.alreadyProcessed())
continue;
// Can we take a shortcut?
if(foo.tryProcessThingsYourself())
continue;
int baz = foo.getBaz();
if(baz < 0) {
int qux = foo.getQux();
if(qux < 0) {
// Error - go to next element
continue;
}
}
// Finally -- do the actual processing
baz = baz * 2;
foo.setBaz(baz);
}
この例は、一連の多段階処理が実行され、各処理がさまざまな場所でさまざまな条件によって中断される可能性があるシナリオで、続行を使用するのがいかに自然であるかを示しています。
注意:plinth投稿された実際の例。2)の内容に従います。
3)原則。何かが中断されたという事実に対応する場合は、continueおよびreturnを使用します。 elseが実際の処理の一部である場合、私はelseを使用します。
考えられるメンテナンスの問題の1つは、関数に複数のリターンがある場合、デバッグ時にブレークポイントを固定したり、リターンでトレースしたりするのが難しいことです。これが問題になることはめったにありませんが、リターンポイントを逃すと苦痛になります。ループ条件とループの先頭はどちらもまだ一意であるため、ループを継続することはそれほど重要ではないと思います。
それとは別に:他のみんなが言うこと。 「いくつかのもの」と「他のもの」の相対的な長さ、重要性、可能性に応じて、最も読みやすいことを行います。ケースが短く、些細で、ありそうもないケースであるほど、特別なケースの制御フローを持つことはそれほど邪魔になりません。
にやにや笑いについては、会社のコードベース全体で「続行」を検索しました。それがどこで使用されているかを知るためだけに。 1つのソリューションで59のプロジェクト全体で695回、約1500のソースファイルを使用します。
それらが使用されているのを私が見る主な方法は、クイックフィルターとしてです。
foreach (Frobozz bar in foo) {
if (QuickFilterExclude(bar))
continue;
// extensive processing
}
予想される例外からの回復:
foreach (Frobozz bar in foo) {
Baz result = new Baz(kDefaultConfiguration);
try {
Baz remoteResult = boo.GetConfiguration();
}
catch (RemoteConnectionException) {
continue;
}
result.Merge(remoteResult);
ReportResult(result);
}
そして最後に州の機械で。
他の人が言ったように、物事が短い場合にのみリターン/コンティニューを使用してください。
個人的には、次のように1行で書き込むことができる場合にのみcontinueを使用します。
while( loopCondition ) {
if( innerCondition ) continue;
//do other stuff
}
コードが醜くならずにこのように書くことができない場合は、if/else。
メソッドまたはループからジャンプするときは、何もする必要がないため、通常はif-returnメソッドを使用します。
かなりの作業が行われているために体が長くなる場合は、if-elseを使用し、おそらく#regionを使用してブロックにわかりやすい名前を付け、制御フローを研究するために簡単に折りたたむことができるようにすることをお勧めします。それまたは別のメソッドを作成します:)
私のコードには次のものがありました:
while(){
boolean intersect = doesIntersect(interval_1,interval_2);
if(!intersect){
array.add(interval_2);
if(// another condition){
// Do some thing here
}
continue;
}
// other stuff to do if intersect
}
continueを使用するか、elseを使用するか混乱していましたが、内部のif条件によってelseが読みにくくなる可能性があると判断したため、continueを使用しました。
読みやすさが重要だと思います!