在Kotlin中何时lambda参数必须为noinline?

sir*_*sel 3 lambda inline kotlin

我经常在Kotlin内联函数中遇到错误,这些函数中必须标记lambda参数noinline。其他时候,lambda参数似乎可以正常工作。我已经阅读了Kotlin的内联函数文档,似乎这是解释该规则的有效段落:

不可嵌入的lambda只能在内联函数内部调用或作为不可嵌入的参数传递,但没有内联的lambda可以以我们喜欢的任何方式进行操作:存储在字段中,周围传递等。

我在解压缩这些概念时遇到了麻烦。具体来说,我不确定我是否完全理解使用内联lambda 不能做的事情(包括“等”中的所有内容),换句话说,那些会使其不符合内联条件的事情。 是否有很好的参考或更多解释/使用示例,这些示例使Kotlin lambda参数无法内联?

Moi*_*ira 5

减少内联Lambda的资格比减少内联,更多的是“无法对内联Lambda进行此操作”。

在这里回答了这个问题

内联方法与任何内联lambda一样直接插入到调用站点中。

重用我的旧示例,

这大致导致main这里:

fun withLambda(lambda: () -> Unit) {
    lambda()
}

inline fun inlinedLambda(lambda: () -> Unit) {
    lambda()
}

fun main(args: Array<String>) {
    withLambda { println("Hello, world") }
    inlinedLambda { println("Hello, world") }
}
Run Code Online (Sandbox Code Playgroud)

被转换为:

fun main(args: Array<String>) {
    withLambda { println("Hello, world") }
    println("Hello, world") // <- Directly inserted!
}
Run Code Online (Sandbox Code Playgroud)

什么,你不能用一个内联拉姆达做的是把它当作一个对象

这意味着您不能将其存储在字段中:

val a = lambda // <-- error
Run Code Online (Sandbox Code Playgroud)

或在其上调用方法:

lambda.toString() // <-- error
Run Code Online (Sandbox Code Playgroud)

因为它不是对象。

也不能将其作为参数传递给另一个函数

func(lambda) // <-- error
Run Code Online (Sandbox Code Playgroud)

除非 lambda标记为crossinline,而另一个函数的参数为inline

这基本上由文档说明。

noinline可以按我们喜欢的任何方式进行操作:存储在字段中,传递周围等。

请注意,某些内联函数可能会调用作为参数传递给它们的lambda。为了表明这一点,需要用crossinline修饰符标记lambda参数:

将内联lambda视为将其代码直接插入到方法中。从概念上讲,它们实际上并不存在,并且“调用”它们只会将其内容插入到调用方法中。