Exception blocks
Protected regions use the ILAsm block form. Each boundary is its own line.
il[1]> .locals init (string m)il[1]> .try {il[1]> ldstr "boom"il[1]> newobj instance void InvalidOperationException::.ctor(string)il[1]> throwil[1]> } catch InvalidOperationException { ┊ [InvalidOperationException]il[1]> callvirt instance string Exception::get_Message()il[1]> stloc mil[1]> leave DONEil[1]> } finally {il[1]> ldstr "finally ran"il[1]> call void Console::WriteLine(string)il[1]> }il[1]> DONE: ldloc mil[1]> retfinally ran = "boom" : stringThe boundaries are:
| Line | Meaning |
|---|---|
.try { |
Opens a protected region. |
} catch T { |
A handler for exceptions of type T. The exception is on the stack when it starts. |
} filter { |
A filter expression. It sees the exception and must end with endfilter, leaving an int32. |
} handler { |
The handler that runs when the filter returned non-zero. |
} finally { |
Runs on every path. Must be the last handler. |
} fault { |
Runs only on the exception path. Must be the last handler. |
} |
Closes the region. |
Leave a region with leave, not ret or br. The stack is empty at every boundary except the
start of a catch, filter, or filter handler, where it holds the exception.
A filter
Section titled “A filter”il[2]> .try {il[2]> ldc.i4 1il[2]> ldc.i4 0il[2]> divil[2]> stloc nil[2]> leave ENDil[2]> } filter {il[2]> isinst DivideByZeroExceptionil[2]> ldnullil[2]> cgt.unil[2]> endfilteril[2]> } handler {il[2]> popil[2]> ldc.i4 42il[2]> stloc nil[2]> leave ENDil[2]> }il[2]> END: ldloc nil[2]> ret = 42 : int32Regions nest: a .try { inside a handler opens an inner region. The label form of .try from
ILAsm is not offered because ILGenerator only exposes structured blocks; the block form
expresses the same programs.