In Kotlin, a coroutine can be abandoned by not resuming it. If a coroutine is abandoned while suspending in a try-block with finally, the finally clause will not be executed until the coroutine is collected.
For example, the following Kotlin code
val seqWithFinally = sequence {
try {
yield(Unit)
yield(Unit)
} finally {
println("finally")
}
}
for (i in seqWithFinally) {
println("for")
break
}
only outputs for
.
As comparisons, both the following C# code
static IEnumerable<int> YieldWithFinally()
{
try
{
yield return 0;
yield return 0;
}
finally
{
Console.WriteLine("finally");
}
}
static void Main(string[] args)
{
foreach (int i in YieldWithFinally())
{
Console.WriteLine("for");
break;
}
}
and the following JS code
function* yieldWithFinally() {
try {
yield 0
yield 0
} finally {
console.log("finally")
}
}
for (let i of yieldWithFinally()) {
console.log("for")
break
}
output
for
finally
For the reasons why Kotlin is designed that way, check KEEP.