Exceptions
A Kotlin function, property accessor, or constructor that throws crosses the bridge as a .NET exception instead of aborting the process. Nothing needs to be written differently in the exported Kotlin to get this: it applies uniformly to every generated call shape.
Catching a specific exception type
A fixed set of Kotlin stdlib exceptions map to the closest .NET type, as a subtype of that type implementing IKotlinException:
Kotlin | C# |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Anything not in this table, including NullPointerException and IndexOutOfBoundsException (.NET reserves NullReferenceException for the CLR itself) and any user-defined exception, arrives as the base KotlinException. catch (ArgumentException) still catches KotlinArgumentException since it inherits from the .NET type.
Catching any Kotlin exception
Every generated exception type, mapped or not, implements IKotlinException:
Use it as a catch filter to handle any Kotlin exception the same way, mapped or not:
Exception.InnerException follows Kotlin's cause chain, one exception per link, each mapped (or falling back to KotlinException) independently:
Where this applies
The same error channel carries a thrown exception out of a property getter or setter, a primary, secondary, or generic class constructor, a value class's constructor (see Value classes), and a data class's generated Copy(), which re-runs the constructor's init validation. A suspend function propagates the exception through the returned Task the ordinary C# async way; see Coroutines and Flow.
A method with a List/Map/Set parameter releases its temporary collection handle whether the call throws or returns; see Collections. For an exception thrown out of a Kotlin implementation of a C#-declared interface, called back from C#, see The bridgeable subset.
Throwable properties
A property declared Throwable, Throwable?, or a stdlib subtype reads from C# as a plain, unthrown Exception (or Exception?), constructed with the same type mapping and cause chain a thrown exception gets, not something you catch:
It binds get-only, even for a var in Kotlin, since C# has no way to construct a typed Kotlin Throwable to satisfy a setter, and each read allocates a new Exception instance: compare Message and type, not references. It works the same way on a sealed subclass's property.
A class whose constructor or copy() takes a Throwable parameter (like Issue56Failure above) gets no generated C# constructor or Copy at all; construct it in Kotlin and expose it through a factory function, as Issue56Sample.DietViolation() does here.
Only a property getter is supported today. A method return, a parameter, List<Throwable>, and a module-local class MyError : Exception() that is not itself exported all keep their existing skip.
Result return values
A kotlin.Result<T> return from an ordinary (non-suspend) function lowers to T: success returns the payload, and Result.failure(e) throws exactly as throw e would, mapped the same way as any other exception. Result<Unit> binds as void, not Unit.
A C# caller cannot tell a modelled Result.failure apart from an unexpected exception: both surface as the same mapped KotlinException subtype, and there is no non-throwing TryRun-style overload.
Only an ordinary return position is supported today. Result<T> at a property, parameter, value-class-own-member, or suspend fun position keeps its existing skip, as does a Result<T> whose payload has no return shape of its own (a sealed base, Flow).