当对象为 null 时何时使用 let/run/apply/with/also?

When to use let/run/apply/with/also when an object is null?

我想运行一段代码取决于变量是否为空,但我仍然不知道什么时候使用let,运行...等等

我想要这样的东西:

myVar?.xxx{
  // do something if is not null
} ?: xxx{
  // do something is myVar is null
}

什么是最好的选择,为什么?谢谢:)

PS 我已经读过 但我仍然不知道什么是最佳做法

最佳做法是 将范围函数与Elvis 运算符链接起来以处理null/not null,因为它的可读性较差且容易出错。仅仅因为您可以 做某事并不意味着您应该做!内联作用域函数提供了强大的功能,因此也有很大的误用和代码可读性差的可能性。

例如,第一个范围函数的 return 值(如果它是 letrun)可能为 null 并导致第二个范围函数也为 运行 和 return 与您预期的不同。

您链接的问题是旧问题,并且从那时起就有很多新的 Kotlin 用户因为 Android 采用它作为推荐语言。许多新用户对内联范围函数感到兴奋,并且可能过于渴望尽可能多地使用它们,而不是仅仅在它们是最合适的工具的地方使用它们。请注意,在显示如何完成的最高投票答案中,建议仍然使用 if/else 因为这更具可读性。

如果myVar是局部变量(或者是局部定义的val属性,没有自定义getter),你应该这样做:

if (myVar != null) {
    // myVar will be smart cast to non-null inside this if block.
    //TODO
else {
    //TODO
}

如果 myVarvar 属性 你可以这样做:

myVar.let { 
    if (it != null) {
        // it will be smart cast to non-null inside this if block.
        //TODO
    else {
        //TODO
    }
}

// OR

val myLocalVar = myVar
if (myLocalVar != null) {
    // myLocalVar will be smart cast to non-null inside this if block.
    //TODO
else {
    //TODO
}

为了解决您的具体问题,如果您真的下定决心要这样做(而您不应该这样做!),使用 myVar.also { } ?: run { } 是最安全的. also 函数不是 return 结果,而是 return 它被调用的结果,因此不存在意外触发两个范围函数的风险。 apply 也可以,但通常如果您有一整块代码到 运行,您不希望将其用作接收器。那将不太可读。对于第二个作用域函数,run 最有意义,因为它不会从外部作用域更改接收器,因此它在这里对可读性造成的影响最小。