.png)
.png)
When working with inline functions, you may encounter crossinline. This keyword is a subtle but important modifier that ensures the safety and predictability of your code when dealing with higher-order functions. In this blog, we’ll explore what crossinline is, why it exists, and how to use it effectively.
What is crossinline?
When a function is marked as inline, it allows its lambdas to be inlined into the calling code. However, if a lambda inside an inline function is passed to another function or launched in a different execution context (e.g., a coroutine or a different thread), it might escape the scope of the calling function. This can lead to unpredictable behavior, such as returning from the wrong context.
crossinline is a modifier that prevents non-local returns from a lambda. In simple terms, it ensures that a lambda passed to an inline function cannot use the return keyword to break out of the outer function.
inline fun executeTask(crossinline task: () -> Unit) { }Why Use crossinline?
When working with higher-order functions, you might want to:
- Prevent Non-local Returns: Ensure that the lambda passed to your function doesn’t accidentally disrupt the flow of the calling function. 
- Enforce Predictability: Restrict the lambda to behave predictably within its execution context. 
- Avoid Scope Escaping: Safeguard your code when a lambda might escape the intended scope due to multi-threading or coroutine contexts. 
Usage of crossinline
Here’s an example to understand how crossinline works:
Without crossinline
inline fun execute(task: () -> Unit) {
    task() // Call the lambda
}
fun main() {
    execute {
        println("Before return")
        return // Non-local return: Exits from `main`
    }
    println("This will never be printed")
}Before returnIn this case, the return inside the lambda causes a non-local return, which exits the main function entirely. The code after the execute call is never executed.
With crossinline
inline fun executeTask(crossinline task: () -> Unit) {
    task() // Call the lambda
}
fun main() {
    executeTask {
        println("Before return")
        // return  // Compiler error: Non-local returns are not allowed
    }
    println("This will be printed")
}Before return
This will be printedBy adding crossinline, the compiler enforces that the lambda cannot use non-local returns, making the code safer and more predictable.
Common Use Cases of crossinline
1. Lambdas in Multi-threaded Environments
When a lambda is passed to a thread or coroutine, crossinline ensures it cannot break out of the calling scope unexpectedly.
inline fun runInThread(crossinline action: () -> Unit) {
    Thread {
        action() // Safely executes without non-local returns
    }.start()
}
fun main() {
    runInThread {
        println("Running in a separate thread")
        // return // Compiler error
    }
}2. Chained Higher-order Functions
When chaining multiple higher-order functions, crossinline ensures predictable behavior for each lambda.
inline fun process(crossinline action: () -> Unit) {
    println("Before action")
    action()
    println("After action")
}
fun main() {
    process {
        println("Inside action")
        // return // Compiler error
    }
    println("End of main")
}Before action
Inside action
After action
End of mainWhen to Use crossinline?
Use crossinline when:
- Your lambda is passed to another function or a different thread, and you want to prevent scope-related issues. 
- Non-local returns from the lambda could lead to unpredictable or undesired behavior. 
- You want to enforce stricter control over the lambda's behavior within the inline function. 
Conclusion
- inlineFunctions: Allow the compiler to copy the function body directly into the call site, improving performance and reducing overhead.
- crossinline: Ensures that lambdas cannot use non-local returns, adding an extra layer of safety and predictability to your code.
- Use - crossinlinethoughtfully in scenarios involving concurrency, multi-threading, or scope-sensitive operations.
Also check:
Noinline in Kotlin - https://www.androidengineers.in/blogs/power-of-noinline-in-kotlin-8yp9fs
Inline in Kotlin - https://www.androidengineers.in/blogs/inline-functions-in-kotlin-ynr1zb
Akshay Nandwana
Founder AndroidEngineers
You can connect with me on:
Book 1:1 Session here Click Here
Join our upcoming classes
https://www.androidengineers.in/courses
Get the latest Android development articles delivered to your inbox.