[kotlin] let ?: run って危険じゃね?説。

スポンサーリンク

突然ですが問題です!

なにがログに出力されるか答えてください。

第一問

// 
fun test1() {
    var hoge: String? = "hoge"
    var hage: String? = "hage"
    hoge?.let { ho ->
        hage?.let { ha ->
            Log.d("test1", "$ho is $ha")
        }
    } ?: run {
        Log.d("test1", "hoge is null")
    }
}

hogehagenullじゃないパターン。

これは簡単だよね。何も考えなくても答えがわかると思う。

答え

test1: hoge is hage

まぁ、そうだよね。両方共nullじゃないんだし、全部出力されるよね。

第二問

// 
fun test2() {
    var hoge: String? = null
    var hage: String? = "hage"
    hoge?.let { ho ->
        hage?.let { ha ->
            Log.d("test2", "$ho is $ha")
        }
    } ?: run {
        Log.d("test2", "hoge is null")
    }
}

hogenullのパターン。

まぁ、これも簡単だと思う。

答え

test2: hoge is null

うん。hogeはnullだし、これが出力されるよね。

第三問

//
fun test3() {
    var hoge: String? = "hoge"
    var hage: String? = null
    hoge?.let { ho ->
        hage?.let { ha ->
            Log.d("test3", "$ho is $ha")
        }
    } ?: run {
        Log.d("test3", "hoge is null")
    }
}

hagenullのパターン。

順当に行けば、hageのletの?:runが無いし、何も表示されないと思うよね。

思ってたんだよね。これがタイトルに繋がるんだよ。

答え

test3: hoge is null

おぉぉぉ・・・・??

hogeがnullじゃないのに「hoge is null」って表示されてしまう。

なんでこんな事が起こるのか

letは最後の評価を返すのでこの場合、hage?.letはnullを返している。

結果、hoge?.letがnull評価されてしまい「hoge is null」が 出力されてしまうってわけ。

予期しないところでnull評価されちゃって変なバグを生む可能性があるのでlet ?: runを使うのを辞めないか?って言うわけ。

どうするか

極力letは使わないようにすれば良いと思う。

個人的に普段の実装はあまりletは使っていない。

letは使わずにalsoを使えば良いと思う。

//
fun test4() {
    var hoge: String? = "hoge"
    var hage: String? = null
    hoge?.also { ho ->
        hage?.let { ha ->
            Log.d("test4", "$ho is $ha")
        }
    } ?: run {
        Log.d("test4", "hoge is null")
    }
}

alsoは何も返さないのでこの場合は何も表示されない。

この場合は本当にhogenullの場合にしか 「hoge is null」 と表示されない。

タイトルとURLをコピーしました