Kotlin :如何使用 if-else 类似的条件与 let 块进行'null'检查



作为代码审查过程的一部分,我将代码中的所有空检查替换为 let 块。

1.具有空检查的代码示例:

if(someValue != null){//run if someValue is not null}
else {//run if someValue is null}

阿拉伯数字。使用 let-run 块后的代码库,如果用于空检查,

var someValue : String? = null
someValue = "SOF"
someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?.run {
//This code block should run only when if someValue is null, like else condition
}

现在 let-run 块的问题是,即使 someValue 不为 null,两个代码块也在运行。所以我无法将代码示例 1 中的 if-else 条件的行为复制到代码示例 2 中的 run-let 条件。

预期的行为是根据值是否为 null 或非 null 来执行 let 或运行代码块。

来源 - kotlinlang.org

  • 执行安全调用(如果接收方为非 null,则调用方法或访问属性(
  • ?:如果左侧值为 null,则取右侧值(猫王运算符(

更改 ?.?:将解决此问题,

代码库如下,将根据空检查运行 let 或运行块。

var someValue : String? = null
someValue = "SOF"
someValue?.also {safeSomeValue->
//This code block will run only if someValue is not null
}?:run {
//This code block will run only if someValue is null, like else condition
}

我正在用代码中的 let 块替换所有空检查

这里的第一个问题是,为什么?这对您来说是否比常规if-else结构更具可读性?我通常会对仅仅为了重构而重构持谨慎态度。

第二个考虑因素更为重要:您正在执行的转换并不等同于原始代码,您实际上是在通过此更改修改行为。采用以下代码段:

var someValue : String? = null
someValue = "SOF"
someValue?.let {safeSomeValue->
    foo(someSafeValue)
    bar(someSafeValue)
} ?: run {
    println("shouldn't happen if someValue != null")
}

您希望run块仅在someValue == null时执行,但这实际上并不是它运行的唯一情况。整个someValue?.let { ... }表达式不仅可以在someValue本身被null时产生null值,而且如果块传递给let返回null。在这种情况下,如果bar()函数调用导致null,则run语句将在之后执行,因此运行您认为是幻想的if-else语句的两个分支。

举一个非常具体的例子来说明 zsmb13 的答案所谈论的内容:

val someValue = 0
someValue?.let { safeSomeValue->
    println("then")
    null
} ?: run {
    println("else")
}

打印thenelse您可以通过使用 also 而不是 let 来解决此问题:

val someValue = 0
someValue?.also { safeSomeValue->
    println("then")
    null
} ?: run {
    println("else")
}

只会打印then .阅读 https://kotlinlang.org/docs/reference/scope-functions.html 并找出原因并证明它确实总是等同于原始if ... else可能会很有用。但我也同意 zsmb13 的观点,这可能是一个坏主意。

你可以创建一个扩展函数,像这样

fun <T> T?.whenNull(block: () -> Unit) = this ?: block()

然后你这样称呼它

somevalue?.let { safeSomeValue ->
    // TODO
}.whenNull {
    // execute when someValue is null
}

有时你会发现以下有用的

inline fun <T> T?.itOrNull(
    ifValue: (T) -> Unit,
    ifNull: () -> Unit
): Unit = when (this) {
    null -> ifNull()
    else -> ifValue(this)
}

用法:

data.title?.itOrNull(
   { view.text = it },
   { view.visibility = View.GONE }
)

您可以编写两个扩展函数,例如:"ifSafe"和"ifNull",它们可以单独使用或链接在一起以模仿 if/else 模式:

fun <T> T?.ifSafe(block: (t:T?) -> Unit) = if (this!=null) block(this) else this
fun Any?.ifNull(block: () -> Unit?) = if (this==null) block().also{return null} else this
fun main() {
    var someValue = 4
    var nullValue = null
    
    someValue.ifSafe { safeSomeValue ->
        println("someValue: "+safeSomeValue.toString())
        null
    }.ifNull{
        println("someValue is null.")
    }
    
    someValue.ifNull{
        println("someValue is null.")
    }.ifSafe{ safeSomeValue ->
        println(safeSomeValue)
    }
    
    nullValue.ifNull{
         println("nullValue is null.")
    }
    
}

相关内容

  • 没有找到相关文章