Kotlin契约帮助编译器将所有列表元素从可为空转换为不可为空?

Kotlin契约帮助编译器将所有列表元素从可为空转换为不可为空?,kotlin,Kotlin,以下情况:我尝试实现一个泛型函数,该函数检查变量列表是否都不为null,并执行lambda,它需要不可为null的变量 我可以链接多个let调用或实现多个“safeLet”函数,使用2,3,4。。。参数,但我仍然希望一个带有列表的泛型函数是可能的 下面是当前代码,以及链接let调用: val parameters = call.receiveParameters() val firstName = parameters["firstName"] val lastName = parameters

以下情况:我尝试实现一个泛型函数,该函数检查变量列表是否都不为null,并执行lambda,它需要不可为null的变量

我可以链接多个let调用或实现多个“safeLet”函数,使用2,3,4。。。参数,但我仍然希望一个带有列表的泛型函数是可能的

下面是当前代码,以及链接let调用:

val parameters = call.receiveParameters()
val firstName = parameters["firstName"]
val lastName = parameters["lastName"]

firstName?.let {
    lastName?.let { userService.add(UserDTO(firstName = firstName, lastName = lastName)) }
}
以下是我当前的“safeLet”功能:

fun  <T> List<Any?>.safeLet(block: () -> T) {
    if(this.contains(null)) return

    block()
}

我可以补充!!在firstName和lastName之后,以避免空检查,但这很难看

我的想法是使用kotlin合同。有没有可能是这样的:

@ExperimentalContracts
fun  <T> List<Any?>.safeLet(block: () -> T) {
    contract {
        returnsNotNull() implies {ALL ELEMENTS ARE NOT NULLABLE}
    }    

    if(this.contains(null)) return

    block()
}
@ExperimentalContracts
有趣的列表。保险柜(区块:()->T){
合同{
returnsNotNull()表示{所有元素都不可为空}
}    
if(this.contains(null))返回
块()
}
提前谢谢


关于“filterNotNull”注释,我现在尝试这样做。仍然不理想,因为我不喜欢在这里使用这个[0]和这个[1],但它可以工作:

allNotNull(firstName, lastName)?.apply {
    userService.add(UserDTO(firstName = this[0], lastName = this[1]))
}


fun <T : Any> allNotNull(vararg elements: T?): List<T>? = if(elements.contains(null)) null else elements.filterNotNull()
allNotNull(firstName,lastName)?。应用{
添加(UserDTO(firstName=this[0],lastName=this[1]))
}
fun allNotNull(vararg元素:T?:列表?=if(elements.contains(null))null else elements.filterNotNull()

您可以使用
绑定功能。它接受另一个函数,您可以在其中使用
bind
将可空引用转换为非空引用

如果将NOTNULL参数传递给
bind
,它将返回该参数。否则,它将暂停执行
绑定

如果暂停执行,
binding
返回
null
,否则返回
绑定
块的结果


以下是如何使用
绑定

binding { userService.add(UserDTO(firstName = firstName.bind(), lastName = lastName.bind())) }
还有一个例子:

fun sumOrNull(a: Int?, b: Int?): Int? = binding { a.bind() + b.bind() }

下面是我的
绑定
实现:

// startCoroutineUninterceptedOrReturn returns either COROUTINE_SUSPENDED or R
@Suppress("UNCHECKED_CAST")
fun <R> binding(block: suspend Binder.() -> R): R? =
    when (val result = block.startCoroutineUninterceptedOrReturn(Binder, BinderContinuation)) {
        COROUTINE_SUSPENDED -> null
        else -> result as R
    }

@RestrictsSuspension
object Binder {
    suspend fun <T> T?.bind(): T {
        if (this != null) return this
        suspendCoroutine<Nothing> {}
    }
}

suspend fun <T> Binder.bind(obj: T?): T {
    contract {
        returns() implies (obj != null)
    }
    return obj.bind()
}

private object BinderContinuation : Continuation<Any?> {
    override val context: CoroutineContext
        get() = EmptyCoroutineContext

    override fun resumeWith(result: Result<Any?>) {
        result.getOrThrow()
    }
}
//startRoutineUnterceptedOrreturn返回挂起的协同路由或R
@抑制(“未选中的_CAST”)
有趣的绑定(块:挂起绑定器)(->R):R=
当(val结果=block.startRoutineUnterceptedorReturn(活页夹,活页夹继续)){
协同程序\u挂起->空
否则->结果为R
}
@限制扩展
对象绑定器{
suspend fun T?.bind():T{
如果(this!=null)返回此
suspendCoroutine{}
}
}
挂起有趣的活页夹。绑定(对象:T?:T){
合同{
returns()表示(obj!=null)
}
返回obj.bind()
}
私有对象绑定继续:继续{
覆盖val上下文:CoroutineContext
get()=EmptyCoroutineContext
覆盖乐趣恢复(结果:结果){
result.getOrThrow()
}
}

您可以使用
绑定功能。它接受另一个函数,您可以在其中使用
bind
将可空引用转换为非空引用

如果将NOTNULL参数传递给
bind
,它将返回该参数。否则,它将暂停执行
绑定

如果暂停执行,
binding
返回
null
,否则返回
绑定
块的结果


以下是如何使用
绑定

binding { userService.add(UserDTO(firstName = firstName.bind(), lastName = lastName.bind())) }
还有一个例子:

fun sumOrNull(a: Int?, b: Int?): Int? = binding { a.bind() + b.bind() }

下面是我的
绑定
实现:

// startCoroutineUninterceptedOrReturn returns either COROUTINE_SUSPENDED or R
@Suppress("UNCHECKED_CAST")
fun <R> binding(block: suspend Binder.() -> R): R? =
    when (val result = block.startCoroutineUninterceptedOrReturn(Binder, BinderContinuation)) {
        COROUTINE_SUSPENDED -> null
        else -> result as R
    }

@RestrictsSuspension
object Binder {
    suspend fun <T> T?.bind(): T {
        if (this != null) return this
        suspendCoroutine<Nothing> {}
    }
}

suspend fun <T> Binder.bind(obj: T?): T {
    contract {
        returns() implies (obj != null)
    }
    return obj.bind()
}

private object BinderContinuation : Continuation<Any?> {
    override val context: CoroutineContext
        get() = EmptyCoroutineContext

    override fun resumeWith(result: Result<Any?>) {
        result.getOrThrow()
    }
}
//startRoutineUnterceptedOrreturn返回挂起的协同路由或R
@抑制(“未选中的_CAST”)
有趣的绑定(块:挂起绑定器)(->R):R=
当(val结果=block.startRoutineUnterceptedorReturn(活页夹,活页夹继续)){
协同程序\u挂起->空
否则->结果为R
}
@限制扩展
对象绑定器{
suspend fun T?.bind():T{
如果(this!=null)返回此
suspendCoroutine{}
}
}
挂起有趣的活页夹。绑定(对象:T?:T){
合同{
returns()表示(obj!=null)
}
返回obj.bind()
}
私有对象绑定继续:继续{
覆盖val上下文:CoroutineContext
get()=EmptyCoroutineContext
覆盖乐趣恢复(结果:结果){
result.getOrThrow()
}
}

filterNoNull()
?不知道filterNotNull在这里如何工作。因此,编译器可以将我的列表从一个列表智能转换到另一个列表,但这无助于智能转换我的列表元素。
filterNoNull()
?不知道filterNotNull如何在这里工作。因此,编译器可以将我的列表从一个列表智能转换到另一个列表,但这无助于智能转换我的列表元素。