C#: When to Use 'when'
Though this might sound like the beginning of a bad Abbott and Costello joke, this post actually addresses an important keyword introduced in C# 6.
Join the DZone community and get the full member experience.
Join For FreeC# 6 introduced the when
keyword. The when
keyword is a way to filter an exception in a catch block by some specific criteria. It was later extended to case statements in C# 7. I'll focus on when to use it in exceptions in this post and address its use in a case statement in another post.
Catch Without When
Let's say you want to handle the same type of exceptions using different criteria. A common scenario for this is an HttpException. When you catch an HttpException, the response code is available on the ResponseCode property. Depending on the response code, you may want to take different actions.
try
{
// do web call
}
catch(HttpException ex)
{
if(ex.WebEventCode >= 500)
{
HandleServerError(ex);
}
else if(ex.WebEventCode >= 400)
{
HandleNotFoundError(ex);
}
...
}
As you can see, handling the error involves a series of if
statements within the catch block. It's not the most elegant looking code. The nested blocks make it more difficult to read, which makes it easier to introduce defects.
Catch When
Enter the when
keyword. Let's look at that same logic using this keyword.
try
{
// do web call
}
catch(HttpException ex) when (ex.WebEventCode >= 500)
{
HandleServerError(ex);
}
catch(HttpException ex) when (ex.WebEventCode >= 400)
{
HandleNotFoundError(ex);
}
Appying when
to the same code reduces nesting. It's intuitive, so it makes the catch blocks easier to understand.
At the time of writing this article, the when
keyword isn't formatted as a keyword in the code styler. I'll take this as evidence that it isn't widely known. It's unfortunate since it's so useful in so many scenarios!
Going Beyond the Exception
It's possible to evaluate more than just the exception in the <code>when</code> statement. Doing so is actually quite useful. Take a look at the following example:
public void DoRecursion(int recurseCount = 3)
{
try
{
throw new Exception("recurse until 0");
}
catch(Exception e) when (recurseCount > 3 && e.Message == "recurse until 0")
{
DoRecursion(recurseCount--);
}
}
As you can see, it's useful to evaluate other variables besides the caught exception. In fact, I used this today to implement a backoff for a web call to an API.
Conclusion
You should start using the when
keyword in scenarios where you have to inspect the exception to make a decision. I wouldn't worry too much about other developers not familiar with this keyword. It's so intuitive, that they'll pick it up quickly! If they don't pick up on it, you can direct them here for an intro or to the official documentation for complete coverage. But, do be careful about object reference exceptions in your when
expression. You wouldn't want to throw anew!
Opinions expressed by DZone contributors are their own.
Comments