2012-02-07 7 views
21

複数if文の代わりにif、else-if文を使うのはいつも慣れている。なぜ私たちはifを使うのか、bodyがreturnステートメントなら複数のifブロックの代わりにelseを返す

例:

int val = -1; 
if (a == b1) { 
    return c1; 
} else if (a == b2) { 
    return c2; 
} ... 
... 
} else { 
    return c11; 
} 

それはどのように実施例2と比較ん:

if (a == b1) { 
    return c1; 
} 
if (a == b2) { 
    return c2; 
} 
.... 

if (a == b11) { 
    return c11; 
} 

を私は賢明な彼らが同じである機能性を知っています。しかし、else-ifの場合はベストプラクティスですか?そうでない場合は?私は、コードベースを別に構造化してよりきれいにすることができると指摘したとき、私の友人の一人によって提起されました。それはすでに私にとって長い間習慣ですが、私は決して尋ねたことはありません。

+1

どの言語を参照していますか? JavaまたはC++? – Billjk

+0

それは私のためのJavaですが、私はC++とJavaの両方のためにこれを使っています... – Lily

+3

C + +で 'operator =='を実装することができますので、大きな違いです(副作用)最適化にも影響します...)。 AFAICRこれはJavaでは動作しません。 – bitmask

答えて

46

if-elseif-elseステートメントは、それが真であるとすぐに比較をやめます。 if-if-ifはすべての比較を行います。最初のほうが効率的です。

編集:ifブロック内でreturnを実行するとコメントで指摘されています。このような場合、またはコントロールがメソッド(例外)を離れる場合は、複数のifステートメントを実行してif-elseif-elseステートメントを実行することに違いはありません。

ただし、とにかくif-elseif-elseを使用することをお勧めします。 ifブロックごとにreturnを実行しないようにコードを変更したとします。その後、効率を維持するために、if-elseif-elseイディオムに変更する必要があります。最初からif-elseif-elseになっていると、将来の編集内容が保存され、コードを読んでいる人にとっては明確になります(私はちょうどあなたのコードの抜け出しを誤解しています)。

+7

投稿は、各条件が「戻り」を行うことを意味するので、1つの条件が成功した後にメソッドの実行が停止します。 –

+0

この例では表示されていません。 – pmr

+0

ああ、それは本当です。 – CanSpice

0

およびelse ifは、2つの連続するifステートメントとは異なります。最初に、CPUが最初のifブランチを取るとき、else ifはチェックされません。 2つの連続したifステートメントでは、最初のifがチェックされて実行されても、次のifもチェックされ、条件が満たされている場合に実行されます。

0

多くのreturnステートメントがあるという単純な理由から、これらのコードスニペットは同等です。 1つのreturn文がある場合は、ここでは不要な構造のelseを使用します。

0

あなたの比較は、if文の本体がメソッドからの制御を返すという事実に基づいています。それ以外の場合は、機能が異なる可能性があります。

この場合、同じ機能を実行します。後者は、私の意見では読みやすく、理解しやすく、使用するための私の選択となります。

0

これらは潜在的に異なることがあります。

ab1およびb2の場合、2つのifブロックを入力します。最初の例では、1つだけを入力します。コンパイラは、ある比較ルールがオブジェクトに適用される可能性があるため、各条件を順番にチェックする必要があるため、最初の例は高速です。それを最適化することは可能かもしれませんが、もしあなたが1つだけを入力したいのであれば、最初のアプローチはより明らかであり、開発者ミスや非効率なコードにつながる可能性は低いので、

6

機能的に同等ではありません。

機能的に同等の唯一の方法は、aの可能なすべての値に対してif文を使用した場合です(つまり、limits.hでCで定義されているINT_INとINT_MAX、または同等のJavaで)。

elseステートメントを使用すると、数百万のif文を記述することなく、残りの可能な値をすべてカバーすることができます。

また、switch/caseステートメントのようにif ... else if ... elseを使用すると、より良いコーディング方法が得られます。コンパイラは、 "default"を指定しないと警告メッセージを表示します"ケースステートメント。これにより、プログラムで無効な値が見落とされるのを防ぎます。例:

double square_root(double x) { 
    if(x > 0.0f) { 
     return sqrt(x); 
    } else if(x == 0.0f) { 
     return x; 
    } else { 
     printf("INVALID VALUE: x must be greater than zero"); 
     return 0.0f; 
    } 
} 

この場合、xの可能な値ごとに何百万ものif文を入力しますか?それを疑う:)

乾杯!

+0

+1は機能的に同等ではないことを指摘しています。 – Perception

+4

コードブロックごとにリターンがある場合は同等です。無効な値の部分はelseブロックにはなく、最後のifの後の通常のコードです。機能的には完全に同等です。 return文がなくても、それぞれのifに対して1つの追加チェックを行うという事実とは別に、機能的に同等のコードを得ることができます(良いコンパイラでもそれを削除できます) – Voo

7

b1 == b2の場合はどうなりますか?これが発生すると(そしてa == b1a == b2場合は?)

、一般的に言えば、次の2つのコードチャンクが異なる行動かもしれない:あなたがしたい場合は

if (a == b1) { 
    /* do stuff here */ 
} 
if (a == b2) { 
    /* do this stuff, as well */ 
} 

if (a == b1) { 
    /* do stuff here, and break out of the test */ 
} 
else if (a == b2) { 
    /* this block is never reached */ 
} 

とを異なるケースの機能を明確に描写するにはif-elseまたはswitch-caseを使用してを1つのテストにします。

複数のケースで異なる機能を使用する場合は、複数のifブロックを別々のテストとして使用します。

あなたが1つのテストを持っているか、複数のテストを持っているかを定義することは、「ベストプラクティス」の問題ではありません。

1

else ifを使用すると、コードが変更されても、より堅牢になると思う傾向があります。もし誰かが関数の制御フローを調整し、返り値をtry-catchの副作用または関数呼び出しに置き換えた場合、すべての条件が本当に排他的であれば、else-ifは困難になります。これは、あなたが一般的な判断を下すために取り組んでいる正確なコードに大きく依存しており、簡潔にトレードオフを考慮する必要があります。

0

CanSpiceの答えは正しいです。パフォーマンスに関する追加の考慮事項は、どの条件が最も頻繁に発生するかを調べることです。たとえば、a == b1が時間の1%だけ発生した場合は、最初に他のケースをチェックすることによってパフォーマンスが向上します。

Gir Loves Tacosの回答も良いです。ベストプラクティスは、すべてのケースをカバーするようにすることです。

1

ifreturnステートメントで。

コードでは、if条件ごとにreturnステートメントがあります。このような状況が発生した場合、これを書くには2つの方法があります。最初は、あなたが、実施例1でそれを書いた方法です:

if (a == b1) { 
    return c1; 
} else if (a == b2) { 
    return c2; 
} else { 
    return c11; 
} 

次のように他のです:

if (a == b1) { 
    return c1; 
} 
if (a == b2) { 
    return c2; 
} 
return c11; // no if or else around this return statement 

あなたのコードを書くのこれらの二つの方法が同一です。

例2でコードを書いた方法は、コンパイラがaのすべての可能な値をカバーしていることを知らないので、C++やJavaでコンパイルしませんでした(Cでは未定義の動作です)。戻り値を返さずに関数の最後まで到達できるコードパスが関数内にあると考えます。各ifブランチでreturn文なし

if (a == b1) { 
    return c1; 
} 
if (a == b2) { 
    return c2; 
} 
... 
if (a == b11) { 
    return c11; 
} 
// what if you set a to some value c12? 

ifブランチでreturn文がなければ、あなたのコードは次の文が真である場合にのみ、機能的に同一である:

  1. あなたはif枝のいずれかでaの値を変化させません。
  2. ==は(数学的意味で)等価関係であり、からb11のどれも同じ等価クラスにはありません。
  3. ==には副作用がありません。ポイント#2(および#3を指す)についてさらに明確にするため

  • ==は常にCまたはJavaにおける同値関係であり、決して副作用を有します。
  • ==演算子(C++、Ruby、Scalaなど)をオーバーライドできる言語では、オーバーライドされた==演算子は等価関係ではなく、副作用を伴う可能性があります。 ==オペレータを上書きした者は、副作用のない等価関係を作成するのに十分な正気であったことは確かですが、保証はありません。
  • タイプ変換規則の緩いJavaScriptやその他のプログラミング言語では、==が非正則でないか、または対称でない言語が組み込まれている場合があります。 (JavaScriptでは、===は等価関係です。)

パフォーマンスに関して、例1は、一致するものの後に比較を実行しないことが保証されています。コンパイラが#2を最適化して余分な比較をスキップすることは可能かもしれませんが、そうは考えにくいでしょう。次の例ではおそらくできません。文字列が長い場合は余分な比較が安くありません。

if (strcmp(str, "b1") == 0) { 
    ... 
} 
if (strcmp(str, "b2") == 0) { 
    ... 
} 
if (strcmp(str, "b3") == 0) { 
    ... 
} 
1

それが一緒にスイッチとすべてのバリエーションであなたの問題のすべての可能な状態を評価するためにはるかに簡単ですので、私は、もし/他の構造を好みます。これは、(デモのために誇張)あなたは、このようなELSEIFが悪い理由PHP、一例として、弱い型付けされた環境で複数のブール評価を行う場合は特にデバッグするより、私が見つけ堅牢かつ迅速です:

if(a && (c == d)) 
{ 
} elseif (b && (!d || a)) 
{ 
} elseif (d == a && (b^2 > c)) 
{ 
} else { 
} 

この問題は4を超えています^ 2 = 16ブール状態。これは単純に事態を悪化させる弱いタイピング効果を実証するためのものです。 3つの状態変数、すなわち、if ab elseif bcタイプの方法に関わる3つの変数問題を想像することはそれほど難しいことではありません。

最適化をコンパイラに任せます。

0

これは、テストする条件によってまったく異なります。あなたが条件の一つは、最終的に他の

if (x > 1) { 
    System.out.println("Hello!"); 
}else if (x < 1) { 
    System.out.println("Bye!"); 
} 

はまた、第一の条件は、第二の意志TRUEの場合ことに注意している場合、あなたがより良い使用を実行したい場合はあなたの例では、最終的にはなく、ベストプラクティスとして違いはありませんあなたが使用する場合は全くチェックしないでください

if (x > 1) { 
    System.out.println("Hello!"); 
} 
if (x < 1) { 
    System.out.println("Bye!"); 
} 

最初の条件がTRUEであっても、2番目の条件がチェックされます。これは最終的にオプティマイザによって解決されるかもしれませんが、私が知る限り、それはそのように動作します。また、最初のものは書かれていて、このように動作するように意図されているため、ロジックが別途要求する場合を除いて、常に最良の選択です。

関連する問題