Subterranean IL: Filter exception handlers

Filter handlers are the second type of exception handler that aren’t accessible from C#. Unlike the other handler types, which have defined conditions for when the handlers execute, filter lets you use custom logic to determine whether the handler should be run. However, similar to a catch block, the filter block does not get run if control flow exits the block without throwing an exception.

Introducing filter blocks

An example of a filter block in IL is the following:

or, in v1 syntax,

In the v1 syntax there is no end label specified for the filter block. This is because the filter block must come immediately before the filter handler; the end of the filter block is the start of the filter handler.

The filter block indicates to the CLR whether the filter handler should be executed using a boolean value on the stack when the endfilter instruction is run; true/non-zero if it is to be executed, false/zero if it isn’t. At the start of the filter block, and the corresponding filter handler, a reference to the exception thrown is pushed onto the stack as a raw object (you have to manually cast to System.Exception).

The allowed IL inside a filter block is tightly controlled; you aren’t allowed branches outside the block, rethrow instructions, and other exception handling clauses. You can, however, use call and callvirt instructions to call other methods.

Filter block logic

To demonstrate filter block logic, in this example I’m filtering on whether there’s a particular key in the Data dictionary of the thrown exception:

Conclusion

Filter exception handlers are another exception handler type that isn’t accessible from C#, however, just like fault handlers, the behaviour can be replicated using a normal catch block:

So, it’s not that great a loss, but it’s still annoying that this functionality isn’t directly accessible. Well, every feature starts off with minus 100 points, so it’s understandable why something like this didn’t make it into the C# compiler ahead of a different feature.