By Michael Stum


2008-09-25 20:56:08 8 Comments

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.

28 comments

@Mat J 2018-07-11 13:12:05

Exception filters are now available in c# 6+. You can do

try
{
       WebId = new Guid(queryString["web"]);
}
catch (Exception ex) when(ex is FormatException || ex is OverflowException)
{
     WebId = Guid.Empty;
}

In C# 7.0+, you can combine this with pattern matching too

try
{
   await Task.WaitAll(tasks);
}
catch (Exception ex) when( ex is AggregateException ae &&
                           ae.InnerExceptions.Count > tasks.Count/2)
{
   //More than half of the tasks failed maybe..? 
}

@joe 2019-07-29 04:46:14

This method is preferred not only because it is simple and clear, but also doesn't have to unwind stack if the conditions are not met, which provides better performance and diagnostic info comparing with rethrow.

@Eugene Gorbovoy 2019-05-27 14:18:24

I want to suggest shortest answer (one more functional style):

        Catch<FormatException, OverflowException>(() =>
            {
                WebId = new Guid(queryString["web"]);
            },
            exception =>
            {
                WebId = Guid.Empty;
            });

For this you need to create several "Catch" method overloads, similar to System.Action:

    [DebuggerNonUserCode]
    public static void Catch<TException1, TException2>(Action tryBlock,
        Action<Exception> catchBlock)
    {
        CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2));
    }

    [DebuggerNonUserCode]
    public static void Catch<TException1, TException2, TException3>(Action tryBlock,
        Action<Exception> catchBlock)
    {
        CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2), typeof(TException3));
    }

and so on as many as you wish. But you need to do it once and you can use it in all your projects (or, if you created a nuget package we could use it too).

And CatchMany implementation:

    [DebuggerNonUserCode]
    public static void CatchMany(Action tryBlock, Action<Exception> catchBlock,
        params Type[] exceptionTypes)
    {
        try
        {
            tryBlock();
        }
        catch (Exception exception)
        {
            if (exceptionTypes.Contains(exception.GetType())) catchBlock(exception);
            else throw;
        }
    }

p.s. I haven't put null checks for code simplicity, consider to add parameter validations.

p.s.2 If you want to return a value from the catch, it's necessary to do same Catch methods, but with returns and Func instead of Action in parameters.

@George 2018-12-07 15:14:45

It is worth mentioning here. You can respond to the multiple combinations (Exception error and exception.message).

I ran into a use case scenario when trying to cast control object in a datagrid, with either content as TextBox, TextBlock or CheckBox. In this case the returned Exception was the same, but the message varied.

try
{
 //do something
}
catch (Exception ex) when (ex.Message.Equals("the_error_message1_here"))
{
//do whatever you like
} 
catch (Exception ex) when (ex.Message.Equals("the_error_message2_here"))
{
//do whatever you like
} 

@Żubrówka 2018-01-23 14:02:59

Maybe try to keep your code simple such as putting the common code in a method, as you would do in any other part of the code that is not inside a catch clause?

E.g.:

try
{
    // ...
}
catch (FormatException)
{
    DoSomething();
}
catch (OverflowException)
{
    DoSomething();
}

// ...

private void DoSomething()
{
    // ...
}

Just how I would do it, trying to find the simple is beautiful pattern

@Fabian 2018-01-05 11:43:42

With C# 7 the answer from Michael Stum can be improved while keeping the readability of a switch statement:

catch (Exception ex)
{
    switch (ex)
    {
        case FormatException _:
        case OverflowException _:
            WebId = Guid.Empty;
            break;
        default:
            throw;
    }
}

@MemphiZ 2018-08-09 15:38:51

This should be the accepted answer as of 2018 IMHO.

@rgoliveira 2018-11-06 15:03:21

Mat J's answer using when is far more elegant/appropriate than a switch.

@Fabian 2018-11-07 13:47:38

@rgoliveira: I agree that for the case asked in the question, the answer by Mat J is more elegant and appropriate. However, it gets hard to read if you have different code you want to execute depending on the exception type or if you want to actually use the instance of the exception. All these scenarios can be treated equally with this switch statement.

@rgoliveira 2018-11-07 16:05:41

@Fabian "if you have different code you want to execute depending on the exception type or if you want to actually use the instance of the exception", then you just make a different catch block, or you'd need to cast it anyway... In my experience, a throw; in your catch block is probably a code smell.

@Fabian 2018-11-08 17:30:43

@rgoliveira: Using a throw in a catch block is OK in several cases see link. Since the case statement actually uses pattern matching link you do not need to cast if you substitute the discard operator link (the underscore) by a variable name. Don't get me wrong, I agree with you that exception filters are a cleaner way doing it, but multiple catch blocks add a lot of curly brackets.

@Jeffrey Rennie 2017-11-15 20:27:32

This is a classic problem every C# developer faces eventually.

Let me break your question into 2 questions. The first,

Can I catch multiple exceptions at once?

In short, no.

Which leads to the next question,

How do I avoid writing duplicate code given that I can't catch multiple exception types in the same catch() block?

Given your specific sample, where the fall-back value is cheap to construct, I like to follow these steps:

  1. Initialize WebId to the fall-back value.
  2. Construct a new Guid in a temporary variable.
  3. Set WebId to the fully constructed temporary variable. Make this the final statement of the try{} block.

So the code looks like:

try
{
    WebId = Guid.Empty;
    Guid newGuid = new Guid(queryString["web"]);
    // More initialization code goes here like 
    // newGuid.x = y;
    WebId = newGuid;
}
catch (FormatException) {}
catch (OverflowException) {}

If any exception is thrown, then WebId is never set to the half-constructed value, and remains Guid.Empty.

If constructing the fall-back value is expensive, and resetting a value is much cheaper, then I would move the reset code into its own function:

try
{
    WebId = new Guid(queryString["web"]);
    // More initialization code goes here.
}
catch (FormatException) {
    Reset(WebId);
}
catch (OverflowException) {
    Reset(WebId);
}

@Tahir Khalid 2018-03-05 00:44:07

This is nice, "ecological coding" i.e. you're thinking ahead about your code & data footprint and making sure no leakage of half processed values. Nice going to follow this pattern thanks Jeffrey!

@Tahir Khalid 2017-04-16 15:51:04

Wanted to added my short answer to this already long thread. Something that hasn't been mentioned is the order of precedence of the catch statements, more specifically you need to be aware of the scope of each type of exception you are trying to catch.

For example if you use a "catch-all" exception as Exception it will preceed all other catch statements and you will obviously get compiler errors however if you reverse the order you can chain up your catch statements (bit of an anti-pattern I think) you can put the catch-all Exception type at the bottom and this will be capture any exceptions that didn't cater for higher up in your try..catch block:

            try
            {
                // do some work here
            }
            catch (WebException ex)
            {
                // catch a web excpetion
            }
            catch (ArgumentException ex)
            {
                // do some stuff
            }
            catch (Exception ex)
            {
                // you should really surface your errors but this is for example only
                throw new Exception("An error occurred: " + ex.Message);
            }

I highly recommend folks review this MSDN document:

Exception Hierarchy

@Athari 2013-04-13 12:18:12

For the sake of completeness, since .NET 4.0 the code can rewritten as:

Guid.TryParse(queryString["web"], out WebId);

TryParse never throws exceptions and returns false if format is wrong, setting WebId to Guid.Empty.


Since C# 7 you can avoid introducing a variable on a separate line:

Guid.TryParse(queryString["web"], out Guid webId);

You can also create methods for parsing returning tuples, which aren't available in .NET Framework yet as of version 4.6:

(bool success, Guid result) TryParseGuid(string input) =>
    (Guid.TryParse(input, out Guid result), result);

And use them like this:

WebId = TryParseGuid(queryString["web"]).result;
// or
var tuple = TryParseGuid(queryString["web"]);
WebId = tuple.success ? tuple.result : DefaultWebId;

Next useless update to this useless answer comes when deconstruction of out-parameters is implemented in C# 12. :)

@Craig 2013-04-17 03:56:53

Precisely--concise, and you totally bypass the performance penalty of handling the exception, the bad form of intentionally using exceptions to control program flow, and the soft focus of having your conversion logic spread around, a little bit here and a little bit there.

@user743382 2013-05-18 11:39:00

I know what you meant, but of course Guid.TryParse never returns Guid.Empty. If the string is in an incorrect format, it sets the result output parameter to Guid.Empty, but it returns false. I'm mentioning it because I've seen code that does things in the style of Guid.TryParse(s, out guid); if (guid == Guid.Empty) { /* handle invalid s */ }, which is usually wrong if s could be the string representation of Guid.Empty.

@nawfal 2013-05-18 20:01:31

wow you have answered the question, except that it is not in the spirit of the question. The larger problem is something else :(

@Craig 2014-02-22 01:55:47

The proper pattern for using TryParse, of course, is more like if( Guid.TryParse(s, out guid){ /* success! */ } else { /* handle invalid s */ }, which leaves no ambiguity like the broken example where the input value might actually be the string representation of a Guid.

@Conor Gallagher 2015-09-14 12:39:11

This answer may indeed be correct in regard to Guid.Parse, but it has missed the entire point of the original question. Which had nothing to do with Guid.Parse, but was in regard to catching Exception vs FormatException/OverflowException/etc.

@beppe9000 2016-03-04 18:26:18

Does TryParse catch the exception internally or compltly avoids it?

@Athari 2016-03-05 06:40:37

@beppe9000 Completely avoids it. You can use .NET Reference Source to view code of system types.

@Fabian 2019-09-18 09:39:18

For the sake of completeness: The out parameter WebId in the first code example seems to be a property. Properties are not allowed as out or ref parameters. So if it really is a Property, an additional local variable has to be introduced.

@Craig 2013-10-12 00:24:15

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 comprise 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;
}

@erroric 2014-03-06 14:55:27

When I first stumbled across this question I was all over the accepted answer. Cool I can just catch all Exceptions and the check the type. I thought it cleaned up the code, but something kept me coming back to the question and I actually read the other answers to the question. I chewed on it for a while, but I have to agree with you. It is more readable and maintainable to use a function to dry up your code than to catch everything, check the type comparing against a list, wrapping code, and throwing. Thanks for coming late and providing an alternative and sane (IMO) option. +1.

@kad81 2014-06-17 08:48:33

Using an error handling function wouldn't work if you wanted to include a throw;. You'd have to repeat that line of code in each catch block (obviously not the end of the world but worth mentioning as it is code that would need to be repeated).

@Craig 2014-06-18 18:39:36

@kad81, that's true, but you would still get the benefit of writing the logging and clean-up code in one place, and changing it in one place if need be, without the goofy semantics of catching the base Exception type then branching based on the exception type. And that one extra throw(); statement in each catch block is a small price to pay, IMO, and still leaves you in the position to do additional exception type-specific cleanup if necessary.

@Reitffunk 2015-03-30 14:20:49

@Craig But how can I return a usual DataType from your ErrorHandler? I just made a method, which parses a string to an enum-class (Enum.Parse()). I want to catch the errors like you described and then just return the enum.NONE in your errorHandler. But I am not able to do it, because return type is void. I am new to C#, so maybe I am just some kind of dumb at the moment.

@Craig 2015-03-30 16:42:12

Hi @Reitffunk, just use Func<Exception, MyEnumType> instead of Action<Exception>. That's Func<T, Result>, with Result being the return type.

@Reitffunk 2015-04-08 14:24:00

Thanks for your reply. I have just tested this, but the problem is, that now the compiler is complaining about "Return statement is missing". He just dont recognize, that it will be returned from the errorHandler()-Function. Do you have a hint, because it would be nice to implement it your way. Workaround would be to just return something at the end, because anyway it would never reached.

@Craig 2015-04-08 17:59:10

@Reitffunk We probably shouldn't take this too far in comments, but basically Action<Exception> results in a delegate for void foo( Exception e ) whereas Func<Exception, MyEnumType> results in a delegate for MyEnumType foo( Exception e ), so you do need to explicitly return an enum value from that inline function.

@Reitffunk 2015-04-16 10:42:10

I got it. Before I was only writing: catch (Exception) {errorHandler(ex); }. What I have to write, if there is a return type other than void: catch (Exception) {return errorHandler(ex);}. I just missed the return. Indeed very logical.

@Conor Gallagher 2015-09-14 12:33:04

I'm in complete agreement here. I too read the first answer and thought seems logical. Moved to a generic 1 for all exception handler. Something inside me made me internally puke... so I reverted the code. Then came across this beauty! This needs to be the accepted answer

@Joseph Daigle 2008-09-25 21:01:49

Catch System.Exception and switch on the types

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

    throw;
}

@Alex Baranosky 2009-02-15 06:51:05

shouldn't it be: else { throw ex; } ?

@Andrew Garrison 2010-08-27 19:48:16

Unfortunately, FxCop (ie - Visual Studio Code Analysis) doesn't like it when you catch Exception.

@Patrick Szalapski 2011-05-23 20:59:22

If you have to do this, wouldn't the code in the OP be better?

@lkg 2011-06-14 19:13:51

I agree with not catching Exception, but, in this case, the catch is a filter. You may have a layer higher that will handle other exception types. I would say this is correct, even though it includes a catch(Exception x). It doesn't modify the program flow, it just handles certain exceptions then lets the rest of the application deal with any other exception types.

@Peter 2011-07-08 05:12:06

The latest version of FxCop does not throw an exception when the code above is used.

@João Bragança 2012-09-04 21:57:49

Not sure what was wrong with the OP's code in the first place. The #1 accepted answer is almost twice as many lines and far less readable.

@David 2013-01-18 17:09:22

But FxCop Shows a warning "Do not catch general exception types" if you just catch Exception instead of a more specialized exception. Therefore this is not an option for me.

@Joel McBeth 2013-02-14 15:47:02

@slypete I think the "return;" is unnecessary, which would make the else correct.

@slypete 2013-02-15 02:47:38

@jcmcbeth The else is correct either way -- just redundant. I prefer more concise code. If you have the choice to rid your codebase of 3 lines vs 1 line while still accomplishing the same task, what do you choose? I choose the former.

@Joel McBeth 2013-02-15 15:51:33

I guess the point I was making is in the original example the function doesn't necessarily end after the try/catch, if you put a return after WebId=Guid.Empty then the function will exit and no code after the try/catch will be executed.

@Xilconic 2013-11-28 14:47:07

@JoãoBragança: While this answer in this example uses more lines, try to imagine if you are dealing with file IO for example, and all you want to do is catch those exceptions and do some log messaging, but only those you expect coming from your file IO methods. Then you often have to deal with a larger number (about 5 or more) different types of exceptions. In that situation, this approach can save you some lines.

@anaximander 2014-10-21 09:50:27

@David The warnings from FxCop (and similar products) are more what you'd call guidelines than actual rules... Catching Exception is fine if you know why it can cause problems and you're taking steps to correct it (like properly re-throwing). Blindly catching Exception is bad because it can silently swallow errors that you weren't expecting, which makes things very hard to debug. This code will rethrow anything that's not the specific error types we're after, so it's safe.

@AnorZaken 2014-12-11 14:58:00

As pointed out in this comment further down here throw; will destroy the callstack, making crash-dumps useless! A very good reason to not do the lazy catch-many-rethrow thing! (throw ex; destroys callstack and stacktrace.)

@DCShannon 2015-03-18 20:20:54

This isn't a general answer with return in there. Most of the time I'm not returning from catch blocks. Should drop the return and restore the else.

@Aaron Hudon 2015-11-04 04:55:51

This syntactic sugar is highly fructose. I can't believe I just stumbled onto the when filter for exception handling.

@horiatu 2016-10-11 20:59:20

The 'when' example is very good! However 'catch (Exception ex) when ...' still rises a flag in ReSharper! To avoid this, observe that both exceptions are children of SystemException, so a better example is : catch (SystemException ex) when (ex is FormatException || ex is OverflowException) { WebId = Guid.Empty; return; } And b.t.w. when expecting other sort of SystemExceptons, just ignore the 'when' clause...

@Patrick Bell 2017-07-21 16:14:23

Late to the party, but doesn't this destroy stack trace information for any function catching the exception higher up the call stack?

@ColinM 2018-06-12 11:48:16

Also late to the party. Not sure where people are getting the call stack & call trace info from, but using throw will not overwrite call stack or trace, whereas throw ex will overwrite the call stack.

@Nicolas 2019-03-11 10:31:28

This answer is outdated, please note Joe's answer below: stackoverflow.com/a/22864936/2477582

@Stefan T 2014-12-08 20:31:11

Joseph Daigle's Answer is a good solution, but I found the following structure to be a bit tidier and less error prone.

catch(Exception ex)
{   
    if (!(ex is SomeException || ex is OtherException)) throw;

    // Handle exception
}

There are a few advantages of inverting the expression:

  • A return statement is not necessary
  • The code isn't nested
  • There's no risk of forgetting the 'throw' or 'return' statements that in Joseph's solution are separated from the expression.

It can even be compacted to a single line (though not very pretty)

catch(Exception ex) { if (!(ex is SomeException || ex is OtherException)) throw;

    // Handle exception
}

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:

catch(Exception ex) when (ex is SomeException || ex is OtherException)
{
    // Handle exception
}

@DCShannon 2015-03-18 20:22:32

+1, this is the best answer. It's better than the top answer mostly because there's no return, although inverting the condition is also a little better.

@Stefan T 2015-03-20 00:35:32

I didn't even think of that. Good catch, I'll add it to the list.

@HimBromBeere 2016-09-22 11:40:40

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:

MyClass instance;
try { instance = ... }
catch(Exception1 e) { Reset(instance); }
catch(Exception2 e) { Reset(instance); }
catch(Exception) { throw; }

void Reset(MyClass instance) { /* reset the state of the instance */ }

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:

try { ... }
catch(Exception e) when(e is Exception1 || e is Exception2)
{ 
    Reset(instance); 
}

@Mark Amery 2017-10-23 22:03:24

"I wonder why no-one noticed that code-duplication." - uh, what? The entire point of the question is to eliminate the code duplication.

@scholar guy 2016-07-29 04:42:02

Just call the try and catch twice.

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
try
{
    WebId = new Guid(queryString["web"]);
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

It is just that Simple!!

@James Esh 2017-02-23 21:40:12

um. this is defeating the purpose of the question. He asks this question to get rid of duplicate code. this answer adds more duplicate code.

@HodlDwon 2013-11-27 21:53:33

Update 2015-12-15: See https://stackoverflow.com/a/22864936/1718702 for C#6. It's a cleaner and now standard in the language.

Geared for people that want a more elegant solution to catch once and filter exceptions, I use an extension method as demonstrated below.

I already had this extension in my library, originally written for other purposes, but it worked just perfectly for type checking on exceptions. Plus, imho, it looks cleaner than a bunch of || statements. Also, unlike the accepted answer, I prefer explicit exception handling so ex is ... had undesireable behaviour as derrived classes are assignable to there parent types).

Usage

if (ex.GetType().IsAnyOf(
    typeof(FormatException),
    typeof(ArgumentException)))
{
    // Handle
}
else
    throw;

IsAnyOf.cs Extension (See Full Error Handling Example for Dependancies)

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter matches at least one of the passed in comparisons.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_comparisons">Values to compare against.</param>
        /// <returns>True if a match is found.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
        {
            // Validate
            p_parameter
                .CannotBeNull("p_parameter");
            p_comparisons
                .CannotBeNullOrEmpty("p_comparisons");

            // Test for any match
            foreach (var item in p_comparisons)
                if (p_parameter.Equals(item))
                    return true;

            // Return no matches found
            return false;
        }
    }
}

Full Error Handling Example (Copy-Paste to new Console app)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.FluentValidation;

namespace IsAnyOfExceptionHandlerSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // High Level Error Handler (Log and Crash App)
            try
            {
                Foo();
            }
            catch (OutOfMemoryException ex)
            {
                Console.WriteLine("FATAL ERROR! System Crashing. " + ex.Message);
                Console.ReadKey();
            }
        }

        static void Foo()
        {
            // Init
            List<Action<string>> TestActions = new List<Action<string>>()
            {
                (key) => { throw new FormatException(); },
                (key) => { throw new ArgumentException(); },
                (key) => { throw new KeyNotFoundException();},
                (key) => { throw new OutOfMemoryException(); },
            };

            // Run
            foreach (var FooAction in TestActions)
            {
                // Mid-Level Error Handler (Appends Data for Log)
                try
                {
                    // Init
                    var SomeKeyPassedToFoo = "FooParam";

                    // Low-Level Handler (Handle/Log and Keep going)
                    try
                    {
                        FooAction(SomeKeyPassedToFoo);
                    }
                    catch (Exception ex)
                    {
                        if (ex.GetType().IsAnyOf(
                            typeof(FormatException),
                            typeof(ArgumentException)))
                        {
                            // Handle
                            Console.WriteLine("ex was {0}", ex.GetType().Name);
                            Console.ReadKey();
                        }
                        else
                        {
                            // Add some Debug info
                            ex.Data.Add("SomeKeyPassedToFoo", SomeKeyPassedToFoo.ToString());
                            throw;
                        }
                    }
                }
                catch (KeyNotFoundException ex)
                {
                    // Handle differently
                    Console.WriteLine(ex.Message);

                    int Count = 0;
                    if (!Validate.IsAnyNull(ex, ex.Data, ex.Data.Keys))
                        foreach (var Key in ex.Data.Keys)
                            Console.WriteLine(
                                "[{0}][\"{1}\" = {2}]",
                                Count, Key, ex.Data[Key]);

                    Console.ReadKey();
                }
            }
        }
    }
}

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter matches at least one of the passed in comparisons.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_comparisons">Values to compare against.</param>
        /// <returns>True if a match is found.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
        {
            // Validate
            p_parameter
                .CannotBeNull("p_parameter");
            p_comparisons
                .CannotBeNullOrEmpty("p_comparisons");

            // Test for any match
            foreach (var item in p_comparisons)
                if (p_parameter.Equals(item))
                    return true;

            // Return no matches found
            return false;
        }

        /// <summary>
        /// Validates if any passed in parameter is equal to null.
        /// </summary>
        /// <param name="p_parameters">Parameters to test for Null.</param>
        /// <returns>True if one or more parameters are null.</returns>
        public static bool IsAnyNull(params object[] p_parameters)
        {
            p_parameters
                .CannotBeNullOrEmpty("p_parameters");

            foreach (var item in p_parameters)
                if (item == null)
                    return true;

            return false;
        }
    }
}

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter is not null, throwing a detailed exception message if the test fails.
        /// </summary>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_name">Name of tested parameter to assist with debugging.</param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void CannotBeNull(this object p_parameter, string p_name)
        {
            if (p_parameter == null)
                throw
                    new
                        ArgumentNullException(
                        string.Format("Parameter \"{0}\" cannot be null.",
                        p_name), default(Exception));
        }
    }
}

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter is not null or an empty collection, throwing a detailed exception message if the test fails.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_name">Name of tested parameter to assist with debugging.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static void CannotBeNullOrEmpty<T>(this ICollection<T> p_parameter, string p_name)
        {
            if (p_parameter == null)
                throw new ArgumentNullException("Collection cannot be null.\r\nParameter_Name: " + p_name, default(Exception));

            if (p_parameter.Count <= 0)
                throw new ArgumentOutOfRangeException("Collection cannot be empty.\r\nParameter_Name: " + p_name, default(Exception));
        }

        /// <summary>
        /// Validates the passed in parameter is not null or empty, throwing a detailed exception message if the test fails.
        /// </summary>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_name">Name of tested parameter to assist with debugging.</param>
        /// <exception cref="ArgumentException"></exception>
        public static void CannotBeNullOrEmpty(this string p_parameter, string p_name)
        {
            if (string.IsNullOrEmpty(p_parameter))
                throw new ArgumentException("String cannot be null or empty.\r\nParameter_Name: " + p_name, default(Exception));
        }
    }
}

Two Sample NUnit Unit Tests

Matching behaviour for Exception types is exact (ie. A child IS NOT a match for any of its parent types).

using System;
using System.Collections.Generic;
using Common.FluentValidation;
using NUnit.Framework;

namespace UnitTests.Common.Fluent_Validations
{
    [TestFixture]
    public class IsAnyOf_Tests
    {
        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void IsAnyOf_ArgumentNullException_ShouldNotMatch_ArgumentException_Test()
        {
            Action TestMethod = () => { throw new ArgumentNullException(); };

            try
            {
                TestMethod();
            }
            catch (Exception ex)
            {
                if (ex.GetType().IsAnyOf(
                    typeof(ArgumentException), /*Note: ArgumentNullException derrived from ArgumentException*/
                    typeof(FormatException),
                    typeof(KeyNotFoundException)))
                {
                    // Handle expected Exceptions
                    return;
                }

                //else throw original
                throw;
            }
        }

        [Test, ExpectedException(typeof(OutOfMemoryException))]
        public void IsAnyOf_OutOfMemoryException_ShouldMatch_OutOfMemoryException_Test()
        {
            Action TestMethod = () => { throw new OutOfMemoryException(); };

            try
            {
                TestMethod();
            }
            catch (Exception ex)
            {
                if (ex.GetType().IsAnyOf(
                    typeof(OutOfMemoryException),
                    typeof(StackOverflowException)))
                    throw;

                /*else... Handle other exception types, typically by logging to file*/
            }
        }
    }
}

@Kaii 2014-10-09 21:02:42

Enhancing the language is not "more elegent". In many places this actually created a maintenance hell. Years later, many programmers are not proud of what monster they created. It's not what you are used to read. It may cause a "huh?" effect, or even severe "WTFs". It's confusing, sometimes. The only thing it does is making the code much harder to grasp for those who need to deal with it later in maintenance - only because a single programmer tried to be "clever". Over the years, i learned that those "clever" solutions are seldomly also the good ones.

@Kaii 2014-10-09 21:07:15

or in a few words: stick with the possibilites the language natively provides. don't try to override the semantics of a language, only because you don't like them. Your collegues (and possibly future-me) will thank you, honestly.

@Marc L. 2016-06-27 14:55:35

Also note, your solution only approximates the semantics of the C# 6 when, as would any version of catch (Exception ex) {if (...) {/*handle*/} throw;}. The real value of when is that the filter runs before the exception is caught, thus avoiding the expense/stack corruption of a re-throw. It takes advantage of a CLR feature that was only previously accessible to VB and MSIL.

@KthProg 2016-12-28 16:02:47

More elegant? This example is so large for such a simple problem and the code is so awful-looking that it wasn't even worth giving a look. Please don't make this code someone else's problem on an actual project.

@maksymiuk 2017-07-27 16:04:25

your entire IsAnyOf method can be rewritten as simply p_comparisons.Contains(p_parameter)

@Tamir Vered 2015-10-07 17:31:46

If you don't want to use an if statement within the catch scopes, in C# 6.0 you can use Exception Filters syntax which was already supported by the CLR in previews versions but existed only in VB.NET/MSIL:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (Exception exception) when (exception is FormatException || ex is OverflowException)
{
    WebId = Guid.Empty;
}

This code will catch the Exception only when it's a InvalidDataException or ArgumentNullException.

Actually, you can put basically any condition inside that when clause:

static int a = 8;

...

catch (Exception exception) when (exception is InvalidDataException && a == 8)
{
    Console.WriteLine("Catch");
}

Note that as opposed to an if statement inside the catch's scope, Exception Filters cannot throw Exceptions, and when they do, or when the condition is not true, the next catch condition will be evaluated instead:

static int a = 7;

static int b = 0;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

Output: General catch.

When there is more then one true Exception Filter - the first one will be accepted:

static int a = 8;

static int b = 4;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

Output: Catch.

And as you can see in the MSIL the code is not translated to if statements, but to Filters, and Exceptions cannot be throw from within the areas marked with Filter 1 and Filter 2 but the filter throwing the Exception will fail instead, also the last comparison value pushed to the stack before the endfilter command will determine the success/failure of the filter (Catch 1 XOR Catch 2 will execute accordingly):

Exception Filters MSIL

Also, specifically Guid has the Guid.TryParse method.

@steven87vt 2018-10-09 13:59:44

+1 for showing multiple when filters and providing an explanation of what happens when multiple filters are used.

@SHM 2015-10-04 07:51:06

in C# 6 the recommended approach is to use Exception Filters, here is an example:

 try
 {
      throw new OverflowException();
 }
 catch(Exception e ) when ((e is DivideByZeroException) || (e is OverflowException))
 {
       // this will execute iff e is DividedByZeroEx or OverflowEx
       Console.WriteLine("E");
 }

@Joe 2014-04-04 13:59:38

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.

@RubberDuck 2015-02-14 13:41:32

Patiently waiting for the official release of 6... I'd like to see this get the checky when that happens.

@Joe 2015-02-14 19:52:07

@RubberDuck I am dying for the null propagation operator from C# 6. Trying to convince the rest of my team that the risk of an unstable language/compiler is worth it. Lots of minor improvements with huge impact. As for getting marked as answer, not important, as long as people realise this will/is possible, I'm happy.

@RubberDuck 2015-02-14 20:02:24

Right?! I'll be taking a good look at my code base in the near future. =) I know the check isn't important, but given the accepted answer will soon be outdated, I'm hoping OP comes back to check this to give it the proper visibility.

@RubberDuck 2015-10-06 16:15:57

That's partially why I haven't awarded it yet @Joe. I want this to be visible. You may want to add an example of an inline filter for clarity though.

@Kashif 2015-05-20 07:48:59

In c# 6.0,Exception Filters is improvements for exception handling

try
{
    DoSomeHttpRequest();
}
catch (System.Web.HttpException e)
{
    switch (e.GetHttpCode())
    {
        case 400:
            WriteLine("Bad Request");
        case 500:
            WriteLine("Internal Server Error");
        default:
            WriteLine("Generic Error");
    }
}

@user247702 2015-05-27 13:37:27

This example does not show any use of exception filters.

@Kashif 2015-05-27 13:42:49

This is standard way to filter exception in c#6.0

@user247702 2015-05-27 13:44:10

Take a look again at what exactly exception filters are. You are not using an exception filter in your example. There's a proper example in this answer posted a year before yours.

@saluce 2015-11-13 16:29:11

An example of exception filtering would be catch (HttpException e) when e.GetHttpCode() == 400 { WriteLine("Bad Request"; }

@Matt 2010-07-30 17:09:19

The accepted answer seems acceptable, except that CodeAnalysis/FxCop will complain about the fact that it's catching a general exception type.

Also, it seems the "is" operator might degrade performance slightly.

CA1800: Do not cast unnecessarily says to "consider testing the result of the 'as' operator instead", but if you do that, you'll be writing more code than if you catch each exception separately.

Anyhow, here's what I would do:

bool exThrown = false;

try
{
    // Something
}
catch (FormatException) {
    exThrown = true;
}
catch (OverflowException) {
    exThrown = true;
}

if (exThrown)
{
    // Something else
}

@René 2010-12-09 11:27:20

But be aware that you can't rethrow the exception without losing the stack trace if you do it like this. (See Michael Stum's comment to the accepted answer)

@Jesse Weigert 2012-03-16 20:03:35

This pattern can be improved by storing the exception(please excuse the poor formatting -- I can't figure out how to put code in comments): Exception ex = null; try { // something } catch( FormatException e){ ex = e; } catch( OverflowException e){ ex = e; } if( ex != null ) { // something else and deal with ex }

@Oliver 2012-11-22 17:19:07

@JesseWeigert: 1. You can use backticks to give a piece of text a mono-spaced font and light grey background. 2. You still won't be able to rethrow the original exception including the stacktrace.

@Clever Neologism 2015-03-10 18:57:22

"Also, it seems the "is" operator might degrade performance slightly. msdn.microsoft.com/en-us/library/ms182271.aspx says to "consider testing the result of the 'as' operator instead", but if you do that, you'll be writing more code than if you catch each exception separately." ... Exceptions are already a "slow" path... you should not be using exceptions in the regular course of your application (thus TryParse over Parse/Exception). Being concerned about micro-optimizations in this code path is overkill.

@Craig 2015-09-15 07:22:11

@CleverNeologism although it may be true that using the is operator may have a slight negative impact on performance, it's also true that an exception handler isn't the place to be overly concerned about optimizing performance. If your app is spending so much time in exception handlers that performance optimization there would make a real difference in app performance, then there are other code issues to take a hard look at. Having said that, I still don't like this solution because you lose the stack trace and because the cleanup is contextually removed from the catch statement.

@saluce 2015-11-13 16:25:20

The only time the is operator degrades performance is if you later perform an as operation (hence they qualify the rule with unnecessarily). If all you are doing is testing the cast without actually needing to perform the cast, then the is operator is exactly what you want to use.

@Michael Stum 2008-09-25 20:56:37

Note that I did find one way to do it, but this looks more like material for The Daily WTF:

catch (Exception ex)
{
    switch (ex.GetType().Name)
    {
        case "System.FormatException":
        case "System.OverflowException":
            WebId = Guid.Empty;
            break;
        default:
            throw;
    }
}

@Aaron 2008-09-25 21:23:19

-1 vote, +5 WTF :-) This should not have been marked as an answer, but it is he-larious.

@Maxymus 2016-01-21 10:27:36

Doesn't matter how simply we could do it. But he didn't sit idle and came up with his view to solve it. Really appreciate.

@Michael Stum 2016-01-21 19:16:45

Don't actually do this though, use Exception Filters in C# 6 or any of the other answers - I put this here specifically as "This is one way, but it's bad and I want to do something better".

@MKesper 2016-06-08 14:02:18

WHY is this bad? I was puzzled you could not use the exception in a switch statement directly.

@Mark Amery 2017-10-23 22:18:03

@MKesper I see a few reasons it's bad. It requires writing the fully-qualified class names as string literals, which is vulnerable to typos that the compiler can't save you from. (This is significant since in many shops error cases are less well-tested and so trivial mistakes in them are more likely to be missed.) It will also fail to match an exception which is a subclass of one of the specified cases. And, due to being strings, the cases will be missed by tools like VS's "Find All References" - pertinent if you want to add a cleanup step everywhere a particular exception is caught.

@Maniero 2015-04-01 12:29:33

If you can upgrade your application to C# 6 you are lucky. The new C# version has implemented Exception filters. So you can write this:

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

Some people think this code is the same as

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

But it´s not. Actually this is the only new feature in C# 6 that is not possible to emulate in prior versions. First, a re-throw means more overhead than skipping the catch. Second, it is not semantically equivalent. The new feature preserves the stack intact when you are debugging your code. Without this feature the crash dump is less useful or even useless.

See a discussion about this on CodePlex. And an example showing the difference.

@Ivan 2017-04-12 13:18:59

Throw without exception preserves the stack, but "throw ex" will overwrite it.

@Konstantin Spirin 2009-01-07 08:07:52

catch (Exception ex)
{
    if (!(
        ex is FormatException ||
        ex is OverflowException))
    {
        throw;
    }
    Console.WriteLine("Hello");
}

@atlaste 2014-10-21 09:44:02

Since I felt like these answers just touched the surface, I attempted to dig a bit deeper.

So what we would really want to do is something that doesn't compile, say:

// Won't compile... damn
public static void Main()
{
    try
    {
        throw new ArgumentOutOfRangeException();
    }
    catch (ArgumentOutOfRangeException)
    catch (IndexOutOfRangeException) 
    {
        // ... handle
    }

The reason we want this is because we don't want the exception handler to catch things that we need later on in the process. Sure, we can catch an Exception and check with an 'if' what to do, but let's be honest, we don't really want that. (FxCop, debugger issues, uglyness)

So why won't this code compile - and how can we hack it in such a way that it will?

If we look at the code, what we really would like to do is forward the call. However, according to the MS Partition II, IL exception handler blocks won't work like this, which in this case makes sense because that would imply that the 'exception' object can have different types.

Or to write it in code, we ask the compiler to do something like this (well it's not entirely correct, but it's the closest possible thing I guess):

// Won't compile... damn
try
{
    throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException e) {
    goto theOtherHandler;
}
catch (IndexOutOfRangeException e) {
theOtherHandler:
    Console.WriteLine("Handle!");
}

The reason that this won't compile is quite obvious: what type and value would the '$exception' object have (which are here stored in the variables 'e')? The way we want the compiler to handle this is to note that the common base type of both exceptions is 'Exception', use that for a variable to contain both exceptions, and then handle only the two exceptions that are caught. The way this is implemented in IL is as 'filter', which is available in VB.Net.

To make it work in C#, we need a temporary variable with the correct 'Exception' base type. To control the flow of the code, we can add some branches. Here goes:

    Exception ex;
    try
    {
        throw new ArgumentException(); // for demo purposes; won't be caught.
        goto noCatch;
    }
    catch (ArgumentOutOfRangeException e) {
        ex = e;
    }
    catch (IndexOutOfRangeException e) {
        ex = e;
    }

    Console.WriteLine("Handle the exception 'ex' here :-)");
    // throw ex ?

noCatch:
    Console.WriteLine("We're done with the exception handling.");

The obvious disadvantages for this are that we cannot re-throw properly, and -well let's be honest- that it's quite the ugly solution. The uglyness can be fixed a bit by performing branch elimination, which makes the solution slightly better:

Exception ex = null;
try
{
    throw new ArgumentException();
}
catch (ArgumentOutOfRangeException e)
{
    ex = e;
}
catch (IndexOutOfRangeException e)
{
    ex = e;
}
if (ex != null)
{
    Console.WriteLine("Handle the exception here :-)");
}

That leaves just the 're-throw'. For this to work, we need to be able to perform the handling inside the 'catch' block - and the only way to make this work is by an catching 'Exception' object.

At this point, we can add a separate function that handles the different types of Exceptions using overload resolution, or to handle the Exception. Both have disadvantages. To start, here's the way to do it with a helper function:

private static bool Handle(Exception e)
{
    Console.WriteLine("Handle the exception here :-)");
    return true; // false will re-throw;
}

public static void Main()
{
    try
    {
        throw new OutOfMemoryException();
    }
    catch (ArgumentException e)
    {
        if (!Handle(e)) { throw; }
    }
    catch (IndexOutOfRangeException e)
    {
        if (!Handle(e)) { throw; }
    }

    Console.WriteLine("We're done with the exception handling.");

And the other solution is to catch the Exception object and handle it accordingly. The most literal translation for this, based on the context above is this:

try
{
    throw new ArgumentException();
}
catch (Exception e)
{
    Exception ex = (Exception)(e as ArgumentException) ?? (e as IndexOutOfRangeException);
    if (ex != null)
    {
        Console.WriteLine("Handle the exception here :-)");
        // throw ?
    }
    else 
    {
        throw;
    }
}

So to conclude:

  • If we don't want to re-throw, we might consider catching the right exceptions, and storing them in a temporary.
  • If the handler is simple, and we want to re-use code, the best solution is probably to introduce a helper function.
  • If we want to re-throw, we have no choice but to put the code in a 'Exception' catch handler, which will break FxCop and your debugger's uncaught exceptions.

@bsara 2012-08-31 20:51:24

This is a variant of Matt's answer (I feel that this is a bit cleaner)...use a method:

public void TryCatch(...)
{
    try
    {
       // something
       return;
    }
    catch (FormatException) {}
    catch (OverflowException) {}

    WebId = Guid.Empty;
}

Any other exceptions will be thrown and the code WebId = Guid.Empty; won't be hit. If you don't want other exceptions to crash your program, just add this AFTER the other two catches:

...
catch (Exception)
{
     // something, if anything
     return; // only need this if you follow the example I gave and put it all in a method
}

@Sepster 2012-10-23 13:41:38

-1 This will execute WebId = Guid.Emtpy in the case where no exception was thrown.

@toong 2012-10-23 21:12:57

@sepster I think the return statement after "// something" is implied here. I do not really like the solution, but this is a constructive variant in the discussion. +1 to undo your downvote :-)

@bsara 2012-10-24 17:27:37

@Sepster toong is right, I assumed that if you wanted a return there, then you would put one...I was trying to make my answer general enough to apply to all situations in case others with similar but not exact questions would benefit as well. However, for good measure, I've add a return to my answer. Thanks for the input.

@nawfal 2013-05-18 11:28:30

Cautioned and Warned: Yet another kind, functional style.

What is in the link doesn't answer your question directly, but it's trivial to extend it to look like:

static void Main() 
{ 
    Action body = () => { ...your code... };

    body.Catch<InvalidOperationException>() 
        .Catch<BadCodeException>() 
        .Catch<AnotherException>(ex => { ...handler... })(); 
}

(Basically provide another empty Catch overload which returns itself)

The bigger question to this is why. I do not think the cost outweighs the gain here :)

@supercat 2013-07-17 02:43:23

One possible advantage of this approach is that there's a semantic difference between catching and rethrowing an exception versus not catching it; in some cases, code should act upon an exception without catching it. Such a thing is possible in vb.net, but not in C# unless one uses a wrapper written in vb.net and called from C#.

@nawfal 2013-07-17 07:20:45

How does on act on an exception without catching it? I do not fully understand you.

@FastAl 2015-10-07 18:15:59

@nawful ... using vb filter - function filt(ex as exception) :LogEx(ex):return false ... then in the catch line: catch ex when filt(ex)

@HimBromBeere 2016-09-22 11:52:54

@FastAl Isn´t this what exception-filters allow in C#6?

@FastAl 2016-09-22 14:31:44

@HimBromBeere yep they're direct analogues

@Maurice 2008-09-25 20:57:26

How about

try
{
    WebId = Guid.Empty;
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
}
catch (OverflowException)
{
}

@Michael Stum 2008-09-25 20:59:36

That works only if the Catch-Code can be fully moved into the Try-Block. But imaging code where you make multiple manipulations to an object, and one in the middle fails, and you want to "reset" the object.

@Maurice 2008-09-25 21:04:02

In that case I would add a reset function and call that from multiple catch blocks.

@FlySwat 2008-09-25 21:01:54

@Micheal

Slightly revised version of your code:

catch (Exception ex)
{
   Type exType = ex.GetType();
   if (exType == typeof(System.FormatException) || 
       exType == typeof(System.OverflowException)
   {
       WebId = Guid.Empty;
   } else {
      throw;
   }
}

String comparisons are ugly and slow.

@Chris Pietschmann 2008-09-25 21:02:47

Why not just use the "is" keyword?

@FlySwat 2008-09-25 21:04:51

If I remember right, "is" is a runtime cast, while typeof is a compile type comparison. But I may be wrong.

@Michael Stum 2008-09-25 21:11:30

After having a look at the C# Specification (7.5.11 typeof and 7.9.10 is), i'm accepting this answer as typeof is unambigous. For some reason, I was also too focused on switch..case, which does not work with GetType(), but an if-statement will work as well.

@Steven A. Lowe 2008-09-25 21:11:54

um...you do realize that this code will silently swallow all other exceptions?

@Greg Beech 2008-09-25 21:12:18

The two checks have different semantics. The '==' check is an exact type check, whereas the 'is' check is an assignability check. I would think that the latter is more appropriate in this type of scenario.

@Michael Stum 2008-09-25 21:12:24

One addition though: "Type exType = ex.GetType(); if(exType = .... || exType = ....)" will result in only 1 call to GetType().

@Michael Stum 2008-09-25 21:15:09

@Greg: I think "is" is not good here: I want to catch exactly System.FormatException. Not sure under what circumstances other types could result in "is System.FormatException" being true, but typeof() seems to be the strictest comparison, as only System.FormatException will be true.

@Greg Beech 2008-09-25 21:19:31

@Michael - If Microsoft introduced, say, StringTooLongException derived from FormatException then it is still a format exception, just a specific one. It depends whether you want the semantics of 'catch this exact exception type' or 'catch exceptions that mean the format of the string was wrong'.

@Greg Beech 2008-09-25 21:21:23

@Michael - Also, note that "catch (FormatException ex) has the latter semantics, it will catch anything derived from FormatException.

@Alex Baranosky 2009-02-15 06:49:18

Shouldn't it be: else { throw ex; } ?

@Samantha Branham 2010-09-22 22:04:22

@Alex No. "throw" without "ex" carries the original exception, including original stack trace, up. Adding "ex" makes the stack trace reset, so you really get a different exception than the original. I'm sure someone else can explain it better than me. :)

@Glenn Slayden 2012-01-11 08:04:41

@FlySwat: 'is' is extremely fast at runtime, probably equal to the equality check, so the question of whether to check for type equality (t.GetType()==typeof(T)) or type subsumption (t is T) can be purely determined by the semantics you desire (or the source code aesthetics you prefer, if there are no type subsumption distinctions involved).

@Paul Alexander 2012-03-27 21:27:13

@FlySwat: I've done tons of reflection work - mostly related to entity mapping. Both is and GetType() == are runtime operations. Neither is implemented by the compiler. However, is is significantly faster than comparing type objects. GetType() is actually a very slow method whereas is can be optimized by the JIT.

@Sam Harwell 2013-07-17 03:47:34

-1: This code is extremely fragile - a library developer could expect to replace throw new FormatException(); with throw new NewlyDerivedFromFormatException(); without breaking code using the library, and it will hold true for all exception handling cases except where someone used == instead of is (or simply catch (FormatException)).

@nicodemus13 2014-03-26 12:29:27

If you're catching exceptions in the first place, I can't see why this common obsession with micro-optimisations is relevant.

@nawfal 2014-08-04 07:35:25

@PaulAlexander GetType is slower only for value types. It should be marginally faster than is in case of reference types as shown in is-vs-typeof. In this case Exception is reference type.

@Greg Beech 2008-09-25 21:03:57

Not in C# unfortunately, as you'd need an exception filter to do it and C# doesn't expose that feature of MSIL. VB.NET does have this capability though, e.g.

Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException

What you could do is use an anonymous function to encapsulate your on-error code, and then call it in those specific catch blocks:

Action onError = () => WebId = Guid.Empty;
try
{
    // something
}
catch (FormatException)
{
    onError();
}
catch (OverflowException)
{
    onError();
}

@Michael Stum 2008-09-25 21:19:01

Interesting idea and another example that VB.net has some interesting advantages over C# sometimes

@MarioDS 2014-10-09 12:15:06

@MichaelStum with that kind of syntax I would hardly call it interesting at all... shudder

@Arne Deruwe 2014-11-26 13:26:22

Exception filters are coming in c# 6! Note the difference of using filters in favor of rethrowing roslyn.codeplex.com/discussions/541301

@AnorZaken 2014-12-11 14:53:36

@ArneDeruwe Thank you for that link! I just learned one more important reason not to re-throw: throw e; destroys stacktrace and callstack, throw; destroys "only" callstack (rendering crash-dumps useless!) A very good reason to use neither if it can be avoided!

@David Carrigan 2015-09-17 16:13:56

If I'm not mistake you can also drop through a catch in VB like you can with case or (switch in c#) statements like so Try Catch ex As ArgumentException Catch ex As NullReferenceException End Try But unfortunately C# does not so we're left with a helper method or to catch generically and determine type.

@camerondm9 2016-08-29 23:40:31

@DavidCarrigan VB.Net has no fall though, for Select...Case or Try...Catch. In your example, the first Catch block implicitly ends when the second Catch block starts, just like how VB.Net handles If...ElseIf.

@Danny 2017-05-24 11:55:43

As of C# 6 exception filters are available! Finally.

Related Questions

Sponsored Content

33 Answered Questions

[SOLVED] How do you assert that a certain exception is thrown in JUnit 4 tests?

13 Answered Questions

[SOLVED] How do you test that a Python function throws an exception?

17 Answered Questions

[SOLVED] Why catch and rethrow an exception in C#?

6 Answered Questions

[SOLVED] Why is it bad style to `rescue Exception => e` in Ruby?

7 Answered Questions

[SOLVED] Manually raising (throwing) an exception in Python

  • 2010-01-12 21:07:40
  • TIMEX
  • 1644799 View
  • 2139 Score
  • 7 Answer
  • Tags:   python exception

5 Answered Questions

[SOLVED] Catch multiple exceptions in one line (except block)

10 Answered Questions

[SOLVED] Can I catch multiple Java exceptions in the same catch clause?

9 Answered Questions

[SOLVED] Proper way to declare custom exceptions in modern Python?

8 Answered Questions

[SOLVED] About catching ANY exception

5 Answered Questions

[SOLVED] Try-catch speeding up my code?

Sponsored Content