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.