为了简化我的实际用例,让我们假设我想在列表中找到最大数量:

var max : Int? = null
listOf(1, 2, 3).forEach {
    if (max == null || it > max) {
        max = it
    }
}

但是,编译失败并显示以下错误:



为什么在此示例中更改封包会阻止智能强制转换工作?

最佳答案

通常,当在lambda函数闭包中捕获了可变变量时,智能强制转换不适用于该变量,无论是在lambda内部还是在创建lambda之后的声明范围中。
这是因为该函数可能会脱离其封闭范围,并可能稍后在不同的上下文中执行,可能多次执行,也可能并行执行。例如,考虑一个假设函数List.forEachInParallel { ... },它对列表的每个元素执行给定的lambda函数,但要并行执行。
编译器必须生成即使在那种严重的情况下也能保持正确的代码,因此它不能假设变量的值在空检查后保持不变,因此无法智能地对其进行强制转换。
但是,List.forEach是完全不同的,因为它是 inline 函数。内联函数的主体及其功能参数的主体(除非该参数具有noinlinecrossinline修饰符)已在调用站点内联,因此编译器可以推理将lambda中的代码作为参数传递给内联函数,就好像它直接编写在调用方法主体中,从而实现了智能转换。
它可以,但是目前没有。仅仅是因为该功能尚未实现。有一个未解决的问题:KT-7186

关于kotlin - 编译错误:不可能智能地强制转换为 '<type>',因为 '<variable>'是由更改的闭包捕获的局部变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38927809/

10-10 02:15