Did you know you can use the 'is not' operator with exception filtering to simplify and improve your error handling in C#?
In this short blog post, I will show you how to use it.
The problem
Imagine you have a function like the following:
private async Task ListenAndHandleMessageAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var result = _subscriberService.Consume(stoppingToken);
try
{
await ProcessMessagesAsync(result, stoppingToken);
}
catch (Exception e)
{
Logger.LogError(e, "There was an error while processing {Message}.", typeof(TMessage).Name);
}
}
}
In my case, this is a BackgroundService
that listens to messages from a Kafka broker. I swallow all exceptions and log them (simplified example here), but what happens if we have a cancellation request? Well, we also gracefully swallow the exception. But I don't want to this. So how can we tackle the problem? Either we just catch more specific exception instead of System.Exception
but that might lead to very repetitive code I like to avoid or I add a check inside the catch block like if (e.GetType() == typeof(OperationCanceledException))
but that doesn't look great either.
The solution - Exception filtering with is not
We can leverage Exception filters that were introduced with C# 6 in combination with the is not
operator:
catch (Exception e) when (e is not OperationCanceledException)
{
Logger.LogError(e, "There was an error while processing {Message}.", typeof(TMessage).Name);
}
Much nicer, isn't it? Why is this useful?
- Improved readability: Your code becomes more self-explanatory, making it easier for fellow developers to understand your intentions.
- Enhanced maintainability: With targeted exception handling, you can easily update or remove specific exceptions without affecting the overall structure of your catch block.
Conclusion
So, the next time you work with error handling in C#, remember to use the 'is not' operator to make your code more efficient and readable.