替换非空断言运算符"!!"以执行数学表达式



在下面的代码中,在减去两个字段之前,会对它们进行 null 检查:

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

是否可以以某种方式删除非空断言运算符!!以执行减法?更好的方法是执行上述代码而不检查 if 语句中是否两者都不为 null。

似乎您将 testingStartTime 和 testingEndTime 声明为可变变量 (var(,因此无法将智能转换为不可为空的类型。有两种惯用方法可以解决您的问题:

  1. 将 testingStartTime 和 testingEndTime 声明为不可变变量 (val((如果可能(

  2. 创建这些变量的两个本地不可变副本,并使用它们来实现智能转换:

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

你可以这样做:

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

这将起作用,但如果testingEndTimetestingStartTimenull,则会null分配给summary.duration.如果需要null任一从属值时的默认值,则可以执行以下操作:

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

或者,如果其中一个相关值为 null,则根本不想更改summary.duration的值,您可以执行以下操作:

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

这个怎么样:

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
}

这与您的代码具有相同的行为,是的,使用更多行,但在我看来看起来更干净。如果你真的不喜欢重新分配变量,你也可以将它们作为函数参数传递。

最新更新