Замена ненулевого оператора утверждения «!!» для выполнения математического выражения

В следующем коде проверка на нулевое значение выполняется для двух полей перед их вычитанием:

if ((testingStartTime != null) && (testingEndTime != null))
    summary.duration = testingEndTime!!.time - testingStartTime!!.time

Можно ли удалить оператор утверждения, не равный нулю !! как-то для того, чтобы выполнить вычитание? Еще лучше был бы способ выполнить вышеупомянутый код, не проверяя, не являются ли оба значения NULL в операторе if.

Всего 6 ответов


Вы можете сделать это как:

summary.duration = testingEndTime?.let { endTime ->
    testingStartTime?.let { startTime -> 
        endTime - startTime
    }
}

Это сработало бы, но присвоило бы значение null для summary.duration если для параметра summary.duration или testingEndTime указано значение null . Если вам нужно значение по умолчанию, когда любое из зависимых значений равно null вы можете сделать:

summary.duration = testingEndTime?.let { endTime ->
    testingStartTime?.let { startTime -> 
        endTime - startTime
    }
} ?: 0

Или, если вы вообще не хотите изменять значение summary.duration если любое из зависимых значений равно нулю, вы можете сделать следующее:

summary.duration = if (testingEndTime != null && testingStartTime != null) {
    testingEndTime - testingStartTime
} else {
    summary.duration
}

Похоже, вы объявляете testStartTime и testingEndTime как изменяемые переменные (var), поэтому интеллектуальное приведение к типу, не допускающему обнуление, невозможно. Есть два идиоматических способа решить вашу проблему:

  1. Объявите testingStartTime и testingEndTime в качестве неизменяемых переменных (val) (если возможно)

  2. Создайте две локальные неизменяемые копии этих переменных и работайте с ними, чтобы сделать возможным интеллектуальное приведение:

    val startTime = testingStartTime
    val endTime = testingEndTime
    if ((startTime != null) && (endTime != null))
        summary.duration = endTime.time - startTime.time

Как насчет этого:

fun main() {
    val x: Int? = null
    val y: Int? = 5

    val z = x-y
    print(z)

}

operator fun Int?.minus(x: Int?) : Int? {
    this ?: return null
    x ?: return null
    return this-x
}

Я знаю, что это слишком много кода, но он может быть использован в нескольких местах.


Если для вас важна краткость, вы можете комбинировать функции области действия, которые поочередно используют приемник или параметр, чтобы вам не приходилось называть параметры. Читаемость может быть сомнительной.

testingStartTime?.let { testingEndTime?.run { summary.duration = it.time - this.time } }

или

summary.duration = testingStartTime?.let { testingEndTime?.run { it.time - this.time } } 
    ?: summary.duration

Просто для удовольствия, вы можете сделать это:

operator fun Double?.minus(other: Double?) = 
    if (this == null || other == null) null else this - other

А потом использовать

summary.duration = (testingStartTime?.time - testingEndTime?.time)?: summary.duration

Но не рекомендую перегружать операторы для примитивов, потому что это может сделать код неразборчивым в другом месте.


Вы уже проверяете на нули заранее, так что в идеале !! не нужны.

Kotlin обычно умело приводит эти переменные к ненулевым типам, но это может быть предотвращено, потому что они являются изменяемыми свойствами класса.
Чтобы это исправить, просто назначьте их локальным переменным:

    val start = testingStartTime
    val end = testingEndTime
    if (start != null && end != null) {
        summary.duration = start.time - end.time
    }

Это похоже на ваш код, и да, использует больше строк, но, на мой взгляд, выглядит чище. Если вам действительно не нравится переназначать переменные, вы можете также передать их как параметры функции, например.


Есть идеи?

10000