It is discouraged to simply catch System.Exception
. Instead, only the "known" exceptions should be caught.
Now, this sometimes leads to unneccessary repetitive code, for example:
try
{
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
WebId = Guid.Empty;
}
catch (OverflowException)
{
WebId = Guid.Empty;
}
I wonder: Is there a way to catch both exceptions and only call the WebId = Guid.Empty
call once?
The given example is rather simple, as it's only a GUID
. But imagine code where you modify an object multiple times, and if one of the manipulations fail in an expected way, you want to "reset" the object
. However, if there is an unexpected exception, I still want to throw that higher.
So you´re repeating lots of code within every exception-switch? Sounds like extracting a method would be god idea, doesn´t it?
So your code comes down to this:
I wonder why no-one noticed that code-duplication.
From C#6 you furthermore have the exception-filters as already mentioned by others. So you can modify the code above to this:
@Micheal
Slightly revised version of your code:
String comparisons are ugly and slow.
As others have pointed out, you can have an
if
statement inside your catch block to determine what is going on. C#6 supports Exception Filters, so the following will work:The
MyFilter
method could then look something like this:Alternatively, this can be all done inline (the right hand side of the when statement just has to be a boolean expression).
This is different from using an
if
statement from within thecatch
block, using exception filters will not unwind the stack.You can download Visual Studio 2015 to check this out.
If you want to continue using Visual Studio 2013, you can install the following nuget package:
At time of writing, this will include support for C# 6.
If you don't want to use an
if
statement within thecatch
scopes, inC# 6.0
you can useException Filters
syntax which was already supported by the CLR in previews versions but existed only inVB.NET
/MSIL
:This code will catch the
Exception
only when it's aInvalidDataException
orArgumentNullException
.Actually, you can put basically any condition inside that
when
clause:Note that as opposed to an
if
statement inside thecatch
's scope,Exception Filters
cannot throwExceptions
, and when they do, or when the condition is nottrue
, the nextcatch
condition will be evaluated instead:When there is more then one
true
Exception Filter
- the first one will be accepted:And as you can see in the
MSIL
the code is not translated toif
statements, but toFilters
, andExceptions
cannot be throw from within the areas marked withFilter 1
andFilter 2
but the filter throwing theException
will fail instead, also the last comparison value pushed to the stack before theendfilter
command will determine the success/failure of the filter (Catch 1
XORCatch 2
will execute accordingly):Also, specifically
Guid
has theGuid.TryParse
method.Joseph Daigle's Answer is a good solution, but I found the following structure to be a bit tidier and less error prone.
There are a few advantages of inverting the expression:
It can even be compacted to a single line (though not very pretty)
Edit: The exception filtering in C# 6.0 will make the syntax a bit cleaner and comes with a number of other benefits over any current solution. (most notably leaving the stack unharmed)
Here is how the same problem would look using C# 6.0 syntax: