if(flag == true)はありなのか?なしなのか?
最近バズってるようなので便乗
blog.meilcli.net
前回の記事ではnon nullな真偽値の場合を前提として考えましたが、nullableな真偽値を考慮すると前回のような結果にならないなということで続編を書きます。
※真偽値としてのネーミングとしてflagはナシだろ~~wという話はナシでお願いします
※以下flag変数はnullableな真偽値とします
最初に前提から
- if文ではnon nullな真偽値(true or false)で判定しなければならない
- KotlinではBoolean?型
- C#ではbool?型(内部的にはNullable<bool>型)
前回との違いは、前回は話の簡素化のためにnullableは考えないとしてましたが、やっぱnullableはクリティカルだなということで考えますという感じです。
1つ目のパターン: ==演算子で比較する
前回はfalseの場合のみ==演算子で比較すればいいみたいなことを書きましたが、nullableな真偽値はif文の判定に使えないので、non nullな真偽値に変換しなければなりません。
if (flag == true) {
// flagがtrueの場合
} else {
// flagがfalseまたはnullの場合
}
if (flag == false) {
// flagがfalseの場合
} else {
// flagがtrueまたはnullの場合
}
言語によって挙動は違うかもしれませんがKotlinとC#の場合は==演算子による比較で手っ取り早くnon nullな真偽値に変換することができます。
2つ目のパターン: Null合体演算子を使う
nullableをnon nullにする場合で手っ取り早く思いつくのはNull合体演算子(Kotlinではエルビス演算子)でflagがnullのときはfalseにするというコードもあるでしょう。
C#の場合
if (flag ?? false) {
// flagがtrueの場合
} else {
// flagがfalseまたはnullの場合
}
if (!flag ?? false) {
// flagがfalseの場合
} else {
// flagがtrueまたはnullの場合
}
Kotlinの場合
if (flag ?: false){
// flagがtrueの場合
} else {
// flagがfalseまたはnullの場合
}
if (flag?.not() ?: false) {
// flagがfalseの場合
} else {
// flagがtrueまたはnullの場合
}
C#の場合は否定演算子!
を使ってますがそうでないと== false
使うとNull合体演算子が無駄になってしまいます。
3つ目のパターン: そもそもnullableなflagにしない
一時変数などを使ってnon nullな真偽値を用意しておこうということです。
場合によっては有用ですが、Null条件演算子?.
, ?[]
を使ってnullが伝搬する場合など、すべての場合で一時変数を使うというのは大変でもあります。
よって3つ目のパターンはケースバイケースな選択肢ということになるでしょう。
1つ目のパターンと2つ目のパターンどっちがいいのか
もはや慣れの領域なので個人差ありとしか言えないと思いますが、1つ目のパターンはflagがtrueの場合に実行して欲しいという表現そのままにflag == true
としています。
flag ?? false
やflag ?: false
よりflag == true
のほうが、どういうときに実行して欲しいかは丸わかりです。
よって、1つ目のパターンはなしかありかの2択で答えるならばなしではないのでありという判断ができます。
結論
- nullableな真偽値の場合は
if(flag == true)
はあり- ただしケースバイケース、一時変数などで回避することもできる
- 他のnullableの概念がある言語ではどうなのかは知りませんし、言語ごとにありかなしかは決まるかと思います