プログラミングをしていると稀によくあるのが次のような if
else if
が連続する場面。特に || (論理和) が入ってくると何が何やら訳がわからなくなる。
if (A && B || C) {
//1
} else if (D) {
//2
} else if (E || F) {
//3
} else {
//4
}
論理式の横方向の位置を揃えるのが難しいのでコードの見た目的にも酷いことになりがち。こういう時は switch
を使って次のように書ける
switch (true) {
case A && B:
case !!C:
//1
break;
case !!D:
//2
break;
case !!E:
case !!F:
//3
break;
default:
//4
}
仕組みはいたって簡単で switch(true)
なのでラベルが true
ならよい。なので C
のようBooleanじゃない可能性がある場合 !!C
のようにして Boolean に変換してやる必要がある。
いっそのこと全てのラベルを !!(expr)
で装飾してしまうのもありか。
これを使えば一見複雑怪奇な if
文もあっさりと理解しやすくなる、、、かも知れないけど、やっぱり普通の無理に一つの論理式にしない方がいいと思う。
if (A && (B || C) || D || (E || (F && G)) || H) {
//
}
switch(true) {
case !!(A && (B || C)):
case !!D:
case !!(E || (F && G)):
case !!H:
//
}
a = A && (B || C);
b = E || (F && G);
if (a || D || b || H) {
// これのほうがよさそう
}
ちなみに、最後のやつは本質的には上の2つと挙動が異なる。それは b
に代入するときに E || (F && G)
が評価されている点だ。もし a
が真なら本来は評価されないはずのものが評価されてしまっている。仮に b
がかなり重たい処理を含むとするとパフォーマンスの低下につながらないとはいいきれない。もしくは何かしらの破壊的な変更を含む場合は、最後の方法をとることはできない。
以下は論理的に同じだけど冗長過ぎる気がする
if (A && (B || C)) {
// 全て
} else if (D) {
// 同じ
} else if (E || (F && G)) {
// 処理を
} else if (H) {
// 行う
}