14 Feb 2015 by Rahul
C# 6 Exception Filters and How they are much more than Syntactic Sugar
What are Exception Filters?
Exception Filters are a new feature in C# 6 which allows you to specify conditions along with a catch block. The catch block is only executed if the condition satisfies. The following code, illustrates the syntax. When you run it, it should display "caught E2".
Is this really a new feature?
In C#, Yes. However support for this in IL was already present and VB.NET already had this feature. Even F# utilized this with its exception pattern matching.
Couldn't we achieve exactly the same by writing conditions inside catch block?
Logically Yes, but there is a fundamental difference. If your condition is in the catch block, you are catching the exception and then checking the condition, while with Exception Filters you are checking the condition before catching the exception. If the condition is not satisfied, the catch block is skipped and the code moves to check if there are other catch blocks matching the exception.
How does that make a difference?
When you catch an excpetion the stack is unwound. You lose critical information because of this in the crash dumps. There is a misconception that if we use the "throw" statement in the catch block instead of "throw ex", your stack is preserved. This results because people only think about the Exception's StackTrace property and not CLR stack. Let's see an example. To try this your self make sure the "Break on Exceptions" for handled excptions is unchecked in Visual Studio settings. (Debug->Exceptions->Uncheck all under Thrown column).
A common scenario is where we catch exceptions and log it, but do nothing else. The following image illustrates where the debugger stops when an exception is thrown. Notice the line where the debugger breaks, and the Locals window:
Now I rewrite some portions, so I can make use of Excetion Filters. I modify the Log function to always return false, and log it using the exception filters instead of inside the catch block. Notice again where the debugger breaks and the Locals window. (EDIT: The syntax has changed since the time the article was originally written. All examples have been updated, except for the image below. Instead of "catch (if(Log()))" it should be read as "catch when (Log())"
Apart from telling you where exactly the exception occured, you can also see the locals window in the second case shows the local variable "localVariable", while the first case is unable to do so, as inside the catch block the local variable is not on the top stack frame. This fairly corresponds to what you see in the crash dumps. Notice how much difference it would make in your investigation, if you are analyzing the crash dumps, with the local values available.
Also, if your code enters a catch block it cannot enter any other catch block. So if you catch an exception and based on some condition, decide not to throw it, it cannot be checked by other catch blocks. In case of exception filters, if the condition is not satisfied, the catch block is skipped and the code moves to check if there are other catch blocks matching the exception.
Related: Try the new C# 6 Features Online