最近のコードレビュー中に、ブロック内で何もすることがなくても、ブロックが使用されるdefault
すべてのファイルにケースを入れるように頼まれswitch
ましたdefault
。つまり、default
ケースを入れて、何も書いてはいけないということです。
これは正しいことですか?それはどのような目的に役立つでしょうか?
最近のコードレビュー中に、ブロック内で何もすることがなくても、ブロックが使用されるdefault
すべてのファイルにケースを入れるように頼まれswitch
ましたdefault
。つまり、default
ケースを入れて、何も書いてはいけないということです。
これは正しいことですか?それはどのような目的に役立つでしょうか?
回答:
default
ステートメントが不要な場合は、次の3つのケースがあるようです。
を入力する値のセットは限られているため、他のケースは残っていませんswitch case
。しかし、これは時間とともに(意図的または偶然に)変更される可能性がありdefault case
、何か変更があった場合は、_間違った値についてユーザーにログを記録するか、警告することができます。
がどのように、どこswitch case
で使用され、どの値が入力されるかを知っています。繰り返しますが、これは変更される可能性があり、追加の処理が必要になる場合があります。
その他の場合は、特別な処理は必要ありません。これが当てはまる場合、default case
受け入れられるコーディングスタイルであり、コードを読みやすくするため、を追加するように求められていると思います。
最初の2つのケースは仮定に基づいています。そのため(定期的なコードレビューがあるため、それほど小さくないチームで作業していると仮定すると)、これらの仮定を立てる余裕はありません。誰があなたのコードで作業するのか、あなたのコードで関数/呼び出しメソッドを呼び出すのかわかりません。同様に、他の人のコードで作業する必要があるかもしれません。同じコーディングスタイルを使用すると、誰か(自分のコードを含む)のコードを簡単に処理できます。
throw new IllegalStateException("Unrecognised case "+myEnum)
エラーの場所と内容を示すのと同様の処理を行う必要があるためです。
else
てif/else if
も、毎回必ず句が必要であることを意味しますか?私には良い考えのように思われない
これは正しいことですか?それはどんな目的に役立つでしょうか?
会社のコーディング標準では、すべてのswitch
ステートメントにデフォルトのケースを要求することは珍しくありません。それの1つの理由は、それが読者が終わりを見つけるのを簡単にするということですswitch
。別の、おそらくより良い理由は、条件が期待と一致しない場合にコードが何をすべきかを少し考えさせることです。要件の理由に関係なく、それが会社の標準である場合、そうでない気密の理由がない限り、それに従う必要があります。
switch
可能性のあるすべての条件にケースが含まれていると思われる場合assert
は、デフォルトのケースにステートメントを入れることをお勧めします。そうすれば、誰かがコードを変更し、あなたswitch
がカバーしていない条件をうっかり追加した場合、彼らはヒットしassert
、コードのその部分に対処する必要があることに気付くでしょう。
あなたがいる場合switch
にのみ可能な条件のいくつかをカバーしていますが、何も特別なが他人のために行う必要があり、あなたは空のデフォルトのケースを残すことができます。そのケースにコメントを追加して、デフォルトのケースが意図的に空であることを示すことをお勧めします。これは、ヒットした条件で作業を行う必要がないためです。
純粋な列挙型を「切り替える」場合、デフォルトのフォールバックを持つことは危険です。後で列挙型に値を追加すると、コンパイラは、カバーされていない新しい値でスイッチを強調表示します。そこにデフォルト句がある場合、コンパイラは沈黙を保ち、見逃す可能性があります。
多くの点で、この質問はよく聞かれる質問と同じです。すべてのオプションをカバーする/ ラダーの最後に句が必要else
if
else if
ですか。
答えは、構文的に言えば、そうではありません。しかし、そこには...
default
句は、(少なくとも)二つの理由が存在し得ます。
otherwise
ケースからのルートが2つあります。これらをソースコードに含めない理由は何もありません。私の哲学は常に非常にシンプルです。2つのオプションの最悪のシナリオを評価し、最も安全な方法を選びます。空のelse
or default
句の場合、最悪の場合のオプションは次のとおりです。
ドラマチック?たぶん...しかし、私のソフトウェアは、それがうまくいかない場合、人々を殺す可能性があります。むしろそのリスクを冒したくない。
余談として、MISRA-Cガイドラインは {所属のプロファイルを参照}をお勧めしますdefault
すべてのための句switch
else
後if
。しかし、あなたが言ったように、いいえ、そうではありません。
Javaは「デフォルト」の文を持っているあなたを強制するものではありませんが、ある良い練習コードは(今のところ)に到達することはないかもしれ場合でも、1時間のすべてを持っています。いくつかの理由があります:
到達不能なデフォルトの句を使用することで、コードの読者に値を検討したことを示し、何をしているかを知ることができます。また、たとえば、新しい列挙値が追加され、スイッチが新しい値を黙って無視してはならないなど、将来の変更も許可します。代わりに例外をスローするか、何か他のことを行うことができます。
渡される予期しない値(enumをオンにしない場合)をキャッチするには、たとえば、予想よりも大きい場合も小さい場合もあります。
「デフォルト」アクションを処理するために-スイッチは特別な動作用です。たとえば、変数はスイッチの外部で宣言されていても、初期化されておらず、各ケースで異なる値に初期化されている場合があります。この場合のデフォルトは、スイッチの直後のコードがエラー/例外をスローしないように、デフォルト値に初期化できます。
デフォルトに何も設定しない(例外、ロギングなどを設定しない)場合でも、デフォルトが発生しないと考えたというコメントでさえ、コードを読みやすくすることができます。しかし、それは個人的な好みに帰着します。
すべてのケースを証明可能で永続的にカバーしていない限り、常にデフォルトを使用する必要があります。費用はかかりません。また、進化するプログラムで切り替えステートメントを維持できない場合の保険です。
本当に他のケースを気にしないと確信している場合、デフォルトはbreak; // do n't careですが、デフォルトはdefaultのようなものでなければなりません:throw new Error( "unexpected value");
同様に、ドロップスルーする効果にコメントを追加せずに、重要なケースの構造を「ドロップスルー」しないでください。Javaは設計段階でこれを間違っていました。
検討する
enum Gender
{
MALE ,
FEMALE ;
}
そして
void run ( Gender g )
{
switch ( g )
{
case MALE :
// code related to males
break ;
default :
assert Gender . FEMALE . equals ( g ) ;
// code related to females
break ;
}
}
これは、MALEケース、FEMALEケース、および例外をスローするデフォルトのケースよりも優れていると主張します。
テスト段階で、コンピューターはgがFEMALEかどうかを確認します。生産中、チェックは省略されます。(ええ、微小最適化!)
さらに重要なことは、100%のコードカバレッジという目標を維持することです。例外をスローするデフォルトのケースを作成した場合、どのようにテストしますか?
Gender . FEMALE . equals ( FEMALE ) ;
評価されfalse
ますか?あなたは意味しましたGender.FEMALE.equals (g)
が、安定している列挙型への参照に依存することができるので、あなたはただ書くことができますg == Gender.FEMALE
。4.(個人的な意見)そのようなコードは読むのがはるかに難しく、少し紛らわしいエラーを生成します。