Kotlin 的 'let' 加 elvis 和意外的 null return 值

Kotlin's 'let' plus elvis, and accidental null return values

今天我很惊讶地得知这种对明显地道的代码的处理失败了:

class QuickTest {

    var nullableThing: Int? = 55

    var nullThing: Int? = null

    @Test
    fun `test let behaviour`() {
        nullableThing?.let {
            print("Nullable thing was non-null")
            nullThing?.apply { print("Never happens") }
        } ?: run {
            fail("This shouldn't have run")
        }
    }
}

这是因为,结合隐式 return,nullThing?.apply{...} 将 null 传递给 let,因此 elvis 运算符对 null 求值并运行第二个块。

这很难检测到。在没有这个陷阱的情况下,我们是否有超越传统 if/else 的适当替代方案?

您可以使用 also 而不是 letalso 将 return nullableThing,而 let 将 return 无论 lambda returns.

参见这篇文章:https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84(点“3. Return 这种与其他类型”)。

您的案例是 also 主题的候选案例。比较两个 block 操作:

fun <T> T.also(block: (T) -> Unit): T
fun <T, R> T.let(block: (T) -> R): R

nullableThing?.also {
    print("Nullable thing was non-null")
    nullThing?.apply { println("Never happens") }
} ?: run {
    fail("This shouldn't have run")
}

另一种惯用的方法是使用when语句

when (nullableThing) {
    null ->
        print("Nullable thing was non-null")
        nullThing?.apply { println("Never happens") }
    else -> fail("This shouldn't have run")
}