Home > Enterprise >  Redundant nullcheck with != null and ?.let?
Redundant nullcheck with != null and ?.let?

Time:08-17

Does the first nullcheck make sense here?

error.timeoutInSeconds != null -> {
    error.timeoutInSeconds?.let {
        doWithNonNullTimeout(it)
    } ?: doWithNull("Timeout is null")
}

When I am not wrong, the second statement

doWithNull("Timeout is null")

is never being reached?

CodePudding user response:

This branch will only be called if timeoutInSeconds is non-null, so why would you expect doWithNull to ever be called? By the way, the ?.let {} ?: … pattern is error prone and should not be used as an alternative to if/else. Because if the last expression of your lambda happens to evaluate to null, then both branches are run. ?.also would be safer, but is less readable than if/else. Example:

foo.bar?.let {
    someBarFunction() // maybe it returns null as a side-effect
} ?: doSomethingAssumingBarIsNull()

// in this case, both someBarFunction() and doSomethingAssumingBarIsNull() are called

When working with a mutable nullable property or nullable property from another class you can do one of these to do it safely:

foo.bar.let { bar ->
    if (bar != null) {
        // use smart-cast not-null bar
    } else {
        // do something when bar is null
    }
}

// or
val bar = foo.bar
if (bar != null) {
    // use smart-cast not-null bar
} else {
    // do something when bar is null
}

// or this, but I don't think it's as readable as either of the above
foo.bar?.also { 
    // use not-null it
} ?: // do something when bar is null

Not sure what to suggest as your alternative because it’s not clear why you would have tried to handle a null case in a branch of your when where you already know it’s not null.

  • Related