2012-01-17 8 views
9

は、私はこのようなループがあるとしましょう:ループの状況、ベストプラクティス?

for (int i = 0; i < someint; i++) 
{ 
    if (i == somecondition) 
    { 
     DoSomething(); 
     continue; 
    } 
    doSomeOtherStuff(); 
} 

対...

for (int i = 0; i < someint; i++) 
{ 
    if (i == somecondition) 
    { 
     DoSomething(); 
    } 
    else 
    { 
     doSomeOtherStuff(); 
    } 
} 

他の上で1つを使用する理由はありますか?それとも、それは単に個人的な好みですか?
私がこれを求めているのはJavaですが、他のほとんどの人にも当てはまると思います。

+1

はかなり確信してコンパイラは、両方を最適化すると、彼らは同じを持っています:doSomethingのとsomeOtherConditionがあること類似していた場合、彼らはおそらく、このコードにつながる、ベースクラスまたはインタフェースで定義された方法の異なる実装する必要がありますパフォーマンス。 – talnicolas

+1

あなたは、単純なコードでは答えが大きく変わることがわかります。これは実際にはループ内の他のコードの量と正確には何かによって決まります。 –

+1

'if'節が短く、' else'節が長くなると、私は最初の形を使います。 –

答えて

16

技術的にはありませんが、この特定のケースでは2番目のものがよりきれいです。

+3

合意した、それはより読みやすいIMHOのようです。 –

2

私は間違いなく2番目の構文を使用します。

可能な限り、ステートメントを続行しないようにしてください。それは私が二構文を好む

7

をデバッグするコードパスがより従うことは難しく、そのための困難に...

for (int i = 0; i < someint; i++) 
{ 
    if (i == somecondition) 
    { 
     DoSomething(); 
     //lets say lot of code 
     //.. 
     //... 
     //... 
     //... 
     continue; 
    } 
    else 
    { 
     doSomeOtherStuff(); 
    } 
} 

あなたがcontinue前にコードの多くを持っていたとしましょう。それはちょうどそれが無条件実行ない

else 
    { 
     doSomeOtherStuff(); 
    } 

を見ることで、すぐには明らかです。

+3

+1:すでに削除されている回答では、40k +評判ポイントを持つメンバーが 'continue'ステートメントを逃しました。私はこれが非常に強力な指標だと思うが、比較的短いif/else文でも、経験豊富なプログラマはまだそれを見逃すことができる。 elseブロックはこれをはるかに明確にします。 – StriplingWarrior

5

私にとって、これはthenelse枝相対的なサイズの間のスプリット何に依存します。一方が他方よりも大規模に大きく、小さい方が論理的に例外的な状況を表している場合、私はthenに短い方を入れて、 「continue」を追加します。それらが大きさとロジックフローの両方でおおよそ等しい場合、私はそれらを自分自身のthenelseブランチに保ちます。この特定のケースで

for (String tok : tokens) { 
    if (isKeyword(tok)) { 
     output.write(tok); 
     continue; 
    } 
    // Do some massive processing of non-keyword tokens here 
    // This block goes on... 
    // and on... 
    // and on... You get the idea 
} 

for (String op : operators) { 
    if (isAdditive(op)) { 
     // Do something for additive ops 
    } else { 
     // Do something for non-additive ops 
    } 
} 
+1

このブロックが繰り返し実行される場合、別の機能(または複数の機能)にリファクタリングするときです。 –

+1

@JamesKanze必ずしもそうである必要はありません。処理がこのブロックに固有で、 'for'の外で定義されたローカルを使用し、再利用のチャンスがない場合、単一の呼び出しでリーフ関数を作成する点はありませんサイト。このコードブロックには素敵な名前を付けるという利点がありますが、コードは別の機能にコードを移動するのと同じくらい効果的です。 – dasblinkenlight

+0

最後に、コードを読みやすく保守したいかどうかという問題です。例外はありますが、私は一般に約10行以上の関数、複数の関数、または最大で2つの入れ子の関数を拒否します。 –

1

、私は2番目のが好適であることを皆に同意します。しかし、私は最初に行くつもりがあります。 DoSomething()が実際にその1つの呼び出しであり、i == someConditionがエッジケースであり、doSomeOtherStuff()が実際には1つの呼び出しではなく20行のコードだった場合は、continueを使用することをお勧めします。このシナリオでは、「まず、この一番端のケースをすばやく処理してみましょう。さて、本当のことをやってみましょう。」

当然のことながら、if-elseについての議論は、私たちの解釈を「私たちが最悪の場合はそうする、そうでなければ本当のことをする」と言い換えることができます。しかし、それは20行すべてがより深く入れ子になっていることを意味します。そして、私には、最初に端のケースを処理して共通の経路に焦点を当てるほうが読みやすくなります。

+0

'doSomeOtherStuff()'が20行のコードである場合、それは別個の関数でなければなりません。 –

+0

@JamesKanze多分、そうではないかもしれません。例えば、 'for'ループが関数内で唯一行われている場合、' myFunction(){for(...){myActualFunction();}を持つ理由はありません。 }} '。そして、20行は20文ではないかもしれませんが、複数の行に分割された長いargを持つメソッドのような、多くの「垂直ノイズ」を含みます。またはコメント。ポイントは、それは判断の呼び出しです。 – yshavit

2

誰もが言ったように、2番目の形式が推奨されています。多くのコーディング標準では、コードの複雑さを増すため、ステートメントの続行と中断を避けることを推奨しています。

ただ、あなたの参照を与えるために:

JSF ++(ルール190)とMISRA C(規則57)は言う:

continue文を使用してはなりません。

これらは安全性が重要なアプリケーションの標準ですが、他のアプリにも適用できます。

ミスラが支払われますが、JSF ++は、こちらから無料でダウンロードすることができます。

http://www.jsf.mil/downloads/documents/JSF_AV_C++_Coding_Standards_Rev_C.doc

それは、C++のためですが、多くのルールが他の言語にも適用することができます。それは価値がある読書!

+2

continueを使用しないと、必然的にcontinueロジック(おそらくブール変数を介して)を手動で実装する必要があるため、必然的に不要なコードが肥大化します。 –

+0

@ edA-qamort-ora-y使用するには、標準をお読みください。初めに、それは単語 "will"、 "shall"、 "must"の使い方に違いがあります。 「shall」ルールは推奨事項であり、可能な限り使用する必要があります。しかし、古いコードで作業している場合を除き、「続行」を避けることはほとんどできません。 –

+1

@ edA-qamort-ora-y 30年近くの経験で、私はこのような事例は見たことがありません。関数があまりにも複雑すぎる場合を除いて---その場合、解決策はそれをより小さな関数にリファクタリングすることであり、既に複雑すぎる関数の複雑さを増やすことではありません。 –

0

私は実際には、最初の2番目のものを好む適切な理由があると信じています。ほとんどの場合、2番目の方がはっきりと読みやすくなります

セイたとえば、あなたがたくさんある、と私はif文の多くを持っていることによって、実際にインデントによって可読性に影響を与え、あなたのループ、内部の条件のたくさん意味:

for (int i = 0 ; i < n ; i++) 
{ 
    if (obj[i]) 
    { 
     doSomething(); 
     if (someOtherCondition() 
     { 
      //........... 
                if (/* some levels down */) 
                { 

                } 
      //..... 
     } 
    } 
} 

私は引数を得る可能性があります"あなたはそれをリファクタリングすることができます"と言っても、、まれにしかできません。

だから、リファクタリングとして、それは多くのより読みやすくすることができます。私はそれはあなたがやっていることに多くを依存だと思う

for (int i = 0 ; i < n ; i++) 
{ 
    if (!obj[i]) 
    { 
     continue; 
    } 
    doSomething(); 
    if (!someOtherCondition() 
    { 
     continue; 
    } 
    //........... 
} 
0

これは簡単な例ですが、私が他のループロジックから「抽出」している条件がある場合、私は可能な限り迅速に引き出します。将来のif文(あなたの最初の例には、将来のロジックを簡素化に抽出することができる状態の場合)例えば:

for (int i = 0 ; i < n ; i++) 
{ 
    if(obj[i] != null && obj[i].instanceOf("A")) { 
     doSomething(); 
    } else if(obj[i] != null && obj[i].instanceOf("B"){ 
     doSomethingElse(); 
    } 
} 

NOWそれは

if(obj[i] == null) { 
    continue; 
} 

に最初の条件を抽出することは、いくつかの混乱を救うことができることは明らかですこのループが強化されるためです。私はこのメソッドをメソッドのパラメーターをテストするために多く使用し、早期に返すか例外をスローします。

また、これはまったくの答えではなく、答えの一部ではありません。あなたが本当にバランスのとれた条件を見た場合、あなたのオブジェクト指向設計に深刻な考えを与えるかもしれません。

for (int i = 0 ; i < n ; i++) 
{ 
    obj[i].doSomething(); 
} 
関連する問題