web-dev-qa-db-ja.com

スイッチケースの使用中にデフォルトのケースを追加する必要はありますか?

最近のコードレビュー中に、defaultで何もする必要がない場合でも、switchブロックが使用されているすべてのファイルにdefaultケースを含めるように依頼されました。つまり、私はdefaultケースを入れて何も書かなければならないということです。

これは正しいことですか?それはどのような目的に役立ちますか?

42
Ankit

defaultステートメントが不要なケースは3つあるようです。

  1. switch caseに入る値のセットが限られているため、他のケースは残りません。ただし、これは時間の経過とともに(意図的または偶発的に)変更される可能性があり、何かが変更された場合にdefault caseを使用すると、ログに記録したり、ユーザーに間違った値について警告したりできます。

  2. switch caseがどこでどのように使用され、どの値が入力されるかがわかります。繰り返しになりますが、これは変更される可能性があり、追加の処理が必要になる場合があります。

  3. その他の場合は、特別な処理は必要ありません。これが事実である場合、default caseを追加するように求められると思います。これは、受け入れられるコーディングスタイルであり、コードを読みやすくするためです。

最初の2つのケースは、仮定に基づいています。したがって(定期的なコードレビューがあるため、それほど小規模ではないチームで作業していると仮定すると)、これらの仮定を立てる余裕はありません。誰がコードを操作するのか、関数の呼び出し/コード内のメソッドの呼び出しを行うのかはわかりません。同様に、他の誰かのコードを操作する必要があるかもしれません。同じコーディングスタイルを使用すると、誰か(自分のコードを含む)のコードを扱いやすくなります。

31
superM

これは正しいチオングですか?それはどのような目的に役立ちますか?

会社のコーディング標準では、すべてのswitchステートメントにデフォルトの大文字小文字の区別が必要になることは珍しくありません。その理由の1つは、読者がswitchの終わりを見つけやすくすることです。別の、おそらくより良い理由は、条件が期待と一致しない場合にコードが何をすべきかを一瞬考えさせることです。要件の理由に関係なく、それが会社の標準である場合、気密な理由がない限り、それに従う必要があります。

switchに考えられるすべての条件のケースが含まれていると思われる場合は、デフォルトのケースにassertステートメントを含めることをお勧めします。こうすることで、誰かがコードを変更し、不注意でswitchがカバーしない条件を追加した場合、assertにヒットし、コードのその部分に対処する必要があることに気付きます。

switchが可能な条件のいくつかしかカバーしていないが、他の条件に対して特別なことをする必要がない場合は、デフォルトのケースを空のままにすることができます。その場合はコメントを追加して、デフォルトのケースが意図的に空であることを示すことをお勧めします。これは、ヒットした条件で実行する必要のある作業がないためです。

29
Caleb

純粋な列挙型を「切り替える」と、デフォルトのフォールバックが危険になります。後で列挙型に値を追加すると、コンパイラーは新しい値がカバーされていないスイッチを強調表示します。そこにdefault句がある場合、コンパイラは沈黙し続け、見落とす可能性があります。

11
Artur

多くの点で、この質問はよくある質問と同じですelse/else ifの最後にif句が必要ですか?すべてのオプションをカバーするラダー

答えは、構文的に言えば、そうではありません。しかし、そこには...

(少なくとも)2つの理由により、default句が存在する可能性があります。

  1. エラーハンドラとして-確かに、絶対にここに来るべきではありません!は主張できる主張ですが、データの破損、またはさらに悪いことに、適切にトラップされない場合、データ検証はプログラム障害へのルートになります。この場合、それは空の句であってはなりません!
  2. 設計/コードカバレッジ-フローチャートの最も単純な形式であっても、ifステートメントからの2つのルートがあり、常にケースからのotherwiseがあります。これらをソースコードに含めない理由はまったくありません。

私の哲学は常に非常に単純です-2つのオプションの最悪のケースのシナリオを評価し、最も安全なものを選びます。空のelseまたはdefault句の場合、最悪の場合のオプションは次のとおりです。

  • それらを含める:「冗長」コードの追加の3行または4行。
  • それらを含めない:不正なデータまたは予期しない状態がトラップされないため、プログラムが失敗する可能性があります。

過激ですか?多分...しかし、私のソフトウェアはそれがうまくいかない場合、人々を殺す可能性があります。私はそのリスクを取らないほうがいい。


余談ですが、 MISRA-Cガイドライン {所属のプロファイルを参照} defaultごとにswitch句を推奨しています

9
Andrew

Javaは 'default'ステートメントを強制しませんが、コードに到達できない場合でも(現在)、常に(常に)1つ持つことは推奨です。これにはいくつかの理由があります。

到達不能なデフォルト句を持つことで、コードの読者に値を検討したことを示し、何をしているのかを知ることができます。たとえば、次のような変更も許可します。新しい列挙値が追加された場合、スイッチは黙って新しい値を無視してはなりません。代わりにそこで例外をスローするか、何か他のことを行うことができます。

渡された予期しない値(enumをオンに切り替えていない場合)をキャッチする-たとえば、期待した値よりも大きいまたは小さい場合があります。

「デフォルト」のアクションを処理するため-スイッチは特別な動作のためのものです。たとえば、変数はスイッチの外部で宣言されていても初期化されず、それぞれのケースで異なるものに初期化されます。この場合のデフォルトでは、デフォルト値に初期化できるため、スイッチの直後のコードでエラーが発生したり、例外がスローされたりしません。

デフォルトに何も入れないことを決定したとしても(例外、ロギングなど)、デフォルトが発生しないという事実を考慮したことを示すコメントであっても、コードを読みやすくするのに役立ちます。しかし、それは個人的な好みに帰着します。

6
Deco

また、それはあなたが使用している言語の哲学に依存することも付け加えておきます。たとえばErlangでは、「クラッシュさせる」ことが一般的なアプローチであり、デフォルトのケースを定義せず、caseステートメントで、条件に合わない状況が発生した場合にエラーを発生させます。

2
Rodrigue

すべてのケースを証明可能かつ永続的にカバーしていない限り、常にデフォルトを使用する必要があります。費用は一切かかりません。進化するプログラムでswitchステートメントを維持できなかった場合の保険になります。

他のケースを気にしないことを本当に確信している場合、デフォルト:break; //気にしないでくださいが、デフォルトのデフォルトはデフォルトのようなものでなければなりません:throw new Error( "unexpected value");

同様に、ドロップするつもりの効果にコメントを追加せずに、重要なケースコンストラクトを「ドロップスルー」しないでください。 Javaこれは設計段階でこれを間違っていました。

0
ddyer