While doing a code review I noticed the following code:
private async Task Handle<TMessage>(TMessage message, CancellationToken token) | |
{ | |
try | |
{ | |
await ProcessMessage(message, token); | |
} | |
catch(OperationCancelledException e) | |
{ | |
//Ignore exception | |
} | |
catch (Exception e) | |
{ | |
Logger.LogError(e, "There was an error while processing {message}.", typeof(TMessage).Name); | |
} | |
} |
In the code above we handle 2 exceptional cases. One specific case when the Task
is cancelled and an OperationCancelledException
is thrown. In that case we ignore the exception and decide to not log it anywhere (we can discuss if this is a good idea or not, but that is not what I want to talk about). And a second exceptional case when any other error type occurs we write it to our logs.
Although there is nothing wrong with the code above, we can further simplify it by introducting an Exception Filter. This allows us to catch and handle exceptions based on requirements you define for the exception. These filters use the catch
statement with the when
keyword:
private async Task Handle<TMessage>(TMessage message, CancellationToken token) | |
{ | |
try | |
{ | |
await ProcessMessage(message, token); | |
} | |
catch (Exception e) when (e is not OperationCanceledException) | |
{ | |
Logger.LogError(e, "There was an error while processing {message}.", typeof(TMessage).Name); | |
} | |
} |
Nice!
Another trick I noticed in the documentation where exception filters are useful is when you want to examine all exceptions but not handle them. This is useful for example when you want to log the exception:
public static void Main() | |
{ | |
try | |
{ | |
string? s = null; | |
Console.WriteLine(s.Length); | |
} | |
catch (Exception e) when (LogException(e)) | |
{ | |
} | |
Console.WriteLine("Exception must have been handled"); | |
} | |
private static bool LogException(Exception e) | |
{ | |
Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}"); | |
Console.WriteLine($"\tMessage: {e.Message}"); | |
return false; | |
} |