C# 6.0 – Exception Filters

[7/30/2015] This article was written against a pre-release version of C# 6.0. Be sure to check out the list of my five favorite C# 6.0 features for content written against the release!

I debated quite a bit with whether I’d write about C# 6.0’s exception filters because honestly, I was indifferent about them at first. What convinced me to include them in this blog series is that the language feature implementation status page lists the feature as done. After playing with the feature a bit, I have to admit that they’re actually pretty nice and do feel like a natural extension to the language as they’ve been implemented. As the CTP notes state, including exception filters with C# increases feature parity with VB and F# (although I still prefer F#’s exception pattern matching, of course).

Traditionally, whenever we’ve caught an exception we’ve had to handle it somehow or rethrow it. Rethrowing exceptions requires more overhead to handle them again and it also has a strong tendency to jack up the call stack as far as reporting goes. If we want to take a different action according to some condition, we need some kind of conditional structure inside the handler. The following code shows a traditional approach to conditionally handling an exception based on its Message property.

try
{
  throw new Exception("Forced Exception");
}
catch (Exception ex)
{
  if (ex.Message.Equals("Forced Exception", StringComparison.InvariantCultureIgnoreCase))
  {
    WriteLine("Filtered handler");
  }

  throw;
}

The preceding snippet is pretty simple but it’s easy to see how more complex filtering scenarios could complicate the handler code. Exception filters improve this story by catching exceptions only when some criteria is met. If the criteria isn’t met, the exception processing logic proceeds as normal, either moving on to the next handler definition or bubbling up. Here’s the above example revised to use exception filtering:

try
{
  throw new Exception("Forced Exception");
}
catch (Exception ex) if (ex.Message.Equals("Forced Exception", StringComparison.InvariantCultureIgnoreCase))
{
  WriteLine("Filtered handler");
}

Here you can see how the condition has been moved into the catch block itself via a contextual if statement. Now the handler body will execute if and only if the expression within the parenthesis evaluates to true. Now, at this point you might be thinking about ways to abuse this and you wouldn’t be alone. In fact, the CTP notes point out how a false returning function can be used as an exception filter to cause some side-effect (such as logging) related to the exception without actually handling the exception.