Categories
.net c# exception

Catch multiple exceptions at once?

2451

It is discouraged to simply catch System.Exception. Instead, only the “known” exceptions should be caught.

Now, this sometimes leads to unnecessary 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 fails expectedly, you want to “reset” the object. However, if there is an unexpected exception, I still want to throw that higher.

11

  • 8

    If you are using .net 4 and above i prefer to use aggregateexception msdn.microsoft.com/en-us/library/system.aggregateexception.aspx

    Oct 18, 2013 at 3:21


  • 2

    Bepenfriends- Since System.Guid does not throw AggregateException, it would be great if you (or someone) could post an answer showing how you would wrap it into an AggregateException etc..

    – weir

    Jan 30, 2014 at 18:53

  • 27

    “It is discouraged to simply catch System.Exception.” -and if method can throw 32 types of exceptions, what one does? write catch for each of them separately?

    May 23, 2015 at 20:22

  • 11

    If a method’s throwing 32 different types of exceptions, it’s badly written. It’s either not catching exceptions it’s own calls are making, it’s doing FAR too much in one method, or the majority/all of those 32 should be a single exception with a reason code.

    – Flynn1179

    May 19, 2017 at 9:02

  • 2

    The accepted answer is out of date; see this one instead, as it’s been updated with an Edit clause at the top: stackoverflow.com/a/19329123/398630

    May 17, 2019 at 20:28


2369

Catch System.Exception and switch on the types

catch (Exception ex)            
{                
    if (ex is FormatException || ex is OverflowException)
    {
        WebId = Guid.Empty;
        return;
    }
    
    throw;
}

1

  • 17

    Obligatory reminder to the editors who aren’t OP: editing in new answers for updates is something we have a rejection reason for, and >2k users aren’t exempt from this. Don’t update other people’s answers to reflect updates to standard versions, or other versions of whatever tech applies to any arbitrary answers – post a new answer instead (pro tip; there’s more rep in that for you). If there additionally are extreme objections against the answer, you leave a comment explaining the problem and link to whatever answer is more applicable now. (And vote on the answer however you’d like)

    Jul 6, 2021 at 21:14

779

EDIT: I do concur with others who are saying that, as of C# 6.0, exception filters are now a perfectly fine way to go: catch (Exception ex) when (ex is ... || ex is ... )

Except that I still kind of hate the one-long-line layout and would personally lay the code out like the following. I think this is as functional as it is aesthetic, since I believe it improves comprehension. Some may disagree:

catch (Exception ex) when (
    ex is ...
    || ex is ...
    || ex is ...
)

ORIGINAL:

I know I’m a little late to the party here, but holy smoke…

Cutting straight to the chase, this kind of duplicates an earlier answer, but if you really want to perform a common action for several exception types and keep the whole thing neat and tidy within the scope of the one method, why not just use a lambda/closure/inline function to do something like the following? I mean, chances are pretty good that you’ll end up realizing that you just want to make that closure a separate method that you can utilize all over the place. But then it will be super easy to do that without actually changing the rest of the code structurally. Right?

private void TestMethod ()
{
    Action<Exception> errorHandler = ( ex ) => {
        // write to a log, whatever...
    };

    try
    {
        // try some stuff
    }
    catch ( FormatException  ex ) { errorHandler ( ex ); }
    catch ( OverflowException ex ) { errorHandler ( ex ); }
    catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}

I can’t help but wonder (warning: a little irony/sarcasm ahead) why on earth go to all this effort to basically just replace the following:

try
{
    // try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}

…with some crazy variation of this next code smell, I mean example, only to pretend that you’re saving a few keystrokes.

// sorta sucks, let's be honest...
try
{
    // try some stuff
}
catch( Exception ex )
{
    if (ex is FormatException ||
        ex is OverflowException ||
        ex is ArgumentNullException)
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

Because it certainly isn’t automatically more readable.

Granted, I left the three identical instances of /* write to a log, whatever... */ return; out of the first example.

But that’s sort of my point. Y’all have heard of functions/methods, right? Seriously. Write a common ErrorHandler function and, like, call it from each catch block.

If you ask me, the second example (with the if and is keywords) is both significantly less readable, and simultaneously significantly more error-prone during the maintenance phase of your project.

The maintenance phase, for anyone who might be relatively new to programming, is going to compose 98.7% or more of the overall lifetime of your project, and the poor schmuck doing the maintenance is almost certainly going to be someone other than you. And there is a very good chance they will spend 50% of their time on the job cursing your name.

And of course FxCop barks at you and so you have to also add an attribute to your code that has precisely zip to do with the running program, and is only there to tell FxCop to ignore an issue that in 99.9% of cases it is totally correct in flagging. And, sorry, I might be mistaken, but doesn’t that “ignore” attribute end up actually compiled into your app?

Would putting the entire if test on one line make it more readable? I don’t think so. I mean, I did have another programmer vehemently argue once long ago that putting more code on one line would make it “run faster.” But of course he was stark raving nuts. Trying to explain to him (with a straight face–which was challenging) how the interpreter or compiler would break that long line apart into discrete one-instruction-per-line statements–essentially identical to the result if he had gone ahead and just made the code readable instead of trying to out-clever the compiler–had no effect on him whatsoever. But I digress.

How much less readable does this get when you add three more exception types, a month or two from now? (Answer: it gets a lot less readable).

One of the major points, really, is that most of the point of formatting the textual source code that we’re all looking at every day is to make it really, really obvious to other human beings what is actually happening when the code runs. Because the compiler turns the source code into something totally different and couldn’t care less about your code formatting style. So all-on-one-line totally sucks, too.

Just saying…

// super sucks...
catch( Exception ex )
{
    if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

6

  • 3

    You can use the new syntax: when (ex is FormatException or OverflowException or ArgumentNullException)

    – Morgan M.

    Sep 20, 2021 at 11:59


  • 2

    @MorganM., I am occasionally a fan of new syntax. This is probably one of those times. 🙂

    Sep 20, 2021 at 19:13

  • I’m fairly sure the program runs faster if you disable word-wrapping in your IDE too. It’s one of those hidden programmer life hacks!

    – AnorZaken

    Jul 4 at 15:52


  • @AnorZaken I feel like you’re conflating performance of the IDE with the runtime performance of the developed software.

    Jul 5 at 17:07

  • @CraigTullis no-no, if you disable word-wrapping, you get fewer lines right? So it runs faster too! 😉

    – AnorZaken

    Jul 7 at 8:27

467

+100

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:

try { … }
catch (Exception e) when (MyFilter(e))
{
    …
}

The MyFilter method could then look something like this:

private bool MyFilter(Exception e)
{
  return e is ArgumentNullException || e is FormatException;
}

Alternatively, this can be all done inline (the right hand side of the when statement just has to be a boolean expression).

try { … }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
    …
}

This is different from using an if statement from within the catch 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:

Install-Package Microsoft.Net.Compilers

At time of writing, this will include support for C# 6.

Referencing this package will cause the project to be built using the
specific version of the C# and Visual Basic compilers contained in the
package, as opposed to any system installed version.

1

  • You are unable to do generic exception logic because you cant name both exceptions you are catching the same variable name.

    – Enrico

    Apr 7 at 14:36