什么时候 lambda 参数在 Kotlin 中必须是 noinline?

When lambda parameters must be noinline in Kotlin?

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

Inlinable lambdas can only be called inside the inline functions or passed as inlinable arguments, but noinline ones can be manipulated in any way we like: stored in fields, passed around etc.

我无法理解这些概念。具体来说,我不确定我是否完全理解使用内联 lambda 不能 做的事情(包括 "etc." 中的所有内容)——换句话说,使它无法被内联的东西。 是否有一个很好的参考或更多 explanation/examples 的用途来取消内联 Kotlin lambda 参数的资格?

更少 "disqualifying" 内联的 lambda 而更多 "this action can't be performed on an inlined 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") }
}

正在转换为:

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

不能对内联 lambda 做的是将其视为对象

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

val a = lambda // <-- error

或对其调用方法:

lambda.toString() // <-- error

因为它不是一个对象。

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

func(lambda) // <-- error

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

文档中基本上已经说明了这一点。

noinline ones can be manipulated in any way we like: stored in fields, passed around etc.

Note that some inline functions may call the lambdas passed to them as parameters ... To indicate that, the lambda parameter needs to be marked with the crossinline modifier:

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