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
而不是 let
。 also
将 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")
}
今天我很惊讶地得知这种对明显地道的代码的处理失败了:
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
而不是 let
。 also
将 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")
}