フォールスルー(クラシック)switchステートメントを使用するのが適切な場合 そのような使用は推奨され奨励されていますか、それともすべてのコストで避けるべきですか?
フォールスルー(クラシック)switchステートメントを使用するのが適切な場合 そのような使用は推奨され奨励されていますか、それともすべてのコストで避けるべきですか?
回答:
これが役に立つ例です。
public Collection<LogItems> GetAllLogItems(Level level) {
Collection<LogItems> result = new Collection<LogItems>();
switch (level) {
// Note: fall through here is INTENTIONAL
case All:
case Info:
result.Add(GetItemsForLevel(Info));
case Warning:
result.Add(GetItemsForLevel(Warning));
case Error:
result.Add(GetItemsForLevel(Error));
case Critical:
result.Add(GetItemsForLevel(Critical));
case None:
}
return result;
}
この種のもの(1つのケースに他のケースが含まれる場合)はかなりまれであると思うので、一部の新しい言語ではフォールオーバーが許可されないか、特別な構文が必要になります。
// INTENTIONAL FALL THROUGH HERE
コメントがありません。
GetItemsForLevel(Info)
呼び出しを呼び出すGetItemsForLevel(Warning)
などして、このコードを簡単に作成できます。
特定の機能を複数の値に適用する必要がある場合に使用します。たとえば、operationCodeというプロパティを持つオブジェクトがあるとします。コードが1、2、3、または4に等しい場合、startOperationX()が必要です。5または6の場合、startOperationY()を開始し、7はstartOperationZ()を開始します。フォールスルーを使用できるのに、機能とブレークを含む7つの完全なケースがあるのはなぜですか?
特定の状況では、特に100個のif-elseステートメントを回避する場合、完全に有効だと思います。=)
switch
複数case
のが関連付けられていることです。それはフォールスルーとは異なります。フォールスルーでは、1つの実行がcase
次の実行に継続しbreak
ます。
フォールスルーケースはまったく問題ありません。多くの場合、列挙は多くの場所で使用され、いくつかのケースを区別する必要がない場合、フォールスルーロジックを使用する方が簡単であることがわかります。
例(説明コメントに注意してください):
public boolean isAvailable(Server server, HealthStatus health) {
switch(health) {
// Equivalent positive cases
case HEALTHY:
case UNDER_LOAD:
return true;
// Equivalent negative cases
case FAULT_REPORTED:
case UNKNOWN:
case CANNOT_COMMUNICATE:
return false;
// Unknown enumeration!
default:
LOG.warn("Unknown enumeration " + health);
return false;
}
}
この種の使用は完全に受け入れられると思います。
case X: case Y: doSomething()
とcase X: doSomething(); case Y: doAnotherThing()
。最初の場合、意図は非常に明示的ですが、2番目の場合、フォールスルーは意図的である場合とそうでない場合があります。私の経験では、最初の例ではコンパイラ/コードアナライザーで警告がトリガーされることはありませんが、2番目の例ではトリガーされます。個人的には、2番目の例を「フォールスルー」と呼ぶだけです。ただし、「公式」の定義についてはわかりません。
による:
1つのケースを次のケースに移行させることに関連する2つの主な問題は次のとおりです。
コードをcaseステートメントの順序に依存させます。決して失敗しない場合はそうではなく、しばしば歓迎されない程度の複雑さを追加します。
1つのケースのコードに1つ以上の後続のケースのコードが含まれていることは明らかではありません。
いくつかの場所は明示的に転倒を禁止しています。そのような場所で仕事をしておらず、練習に慣れていて、問題のコードを壊しても実際の苦痛が生じないなら、それは世界で最悪のものではないかもしれません。ただし、それを行う場合は、注意を引くコメントを近くに置いて、後で来る人(将来のあなたを含む)に警告するようにしてください。
ここに、私の人生をよりシンプルにするフォールスルーの簡単な(確かに不完全な(うるう年の特別な処理なし))例があります:
function get_julian_day (date) {
int utc_date = date.getUTCDate();
int utc_month = date.getUTCMonth();
int julian_day = 0;
switch (utc_month) {
case 11: julian_day += 30;
case 10: julian_day += 31;
case 9: julian_day += 30;
case 8: julian_day += 31;
case 7: julian_day += 31;
case 6: julian_day += 30;
case 5: julian_day += 31;
case 4: julian_day += 30;
case 3: julian_day += 31;
case 2: julian_day += 28;
case 1: julian_day += 31;
default: break;
}
return julian_day + utc_date;
}
あるケースから別のケースに進む必要があると感じた場合(まれに、確かに)、私は非常に明確goto case
にしたいと思います。
落下は非常にまれであり、コードを読んでいるときに見落とすのが非常に簡単なので、明示的にするのが適切であると感じます-そして、場合であっても、後藤は親指のように目立つはずです。
また、caseステートメントが並べ替えられたときに発生する可能性のあるバグを回避するのにも役立ちます。