65

I have a method that can throw two different exceptions, CommuncationException and SystemException. In both cases I do the same three-line code block.

try {
 ...
}

catch (CommunicationException ce) {
   ...
}

catch {SystemExcetion se) {
   ... 
}

Is there any possibility to do it like that?

try {
   ...
}

catch (CommunicationException ce, SystemException se) {
   ...
}

Then I would not have to write this much code. I know I could extract the exception handling to a private method, but since the code is only 3 lines long, the method definition would take more code than the body itself.

Maniero
  • 10,311
  • 6
  • 40
  • 85
RoflcoptrException
  • 51,941
  • 35
  • 152
  • 200
  • I'm not entirely sure you'd want to anyway. Wouldn't you still end up writing code to separate the exceptions - `if (ce...) else (se...)`. In the end it might look more messy anyway. – James Wiseman Apr 06 '11 at 08:23
  • A similar question exists here http://stackoverflow.com/questions/136035/catch-multiple-exceptions-at-once but you'd be catching the base `Exception` and you'd still need to write code to check the derived type for `CommunicationException` or `SystemException`... it's more LOC than your existing `catch {} catch {}`, so not worth the hassle. – BoltClock Apr 06 '11 at 08:23
  • @James Wiseman No I wouldn't need an if/else since both exception handlings are exactly the same. – RoflcoptrException Apr 06 '11 at 08:24
  • Does this answer your question? [Catch multiple exceptions at once?](https://stackoverflow.com/questions/136035/catch-multiple-exceptions-at-once) – ahmed hamdy May 27 '20 at 14:31

8 Answers8

208

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 CommunicationException || ex is SystemException) {
    //handle it
}

Some people think this code is the same as

catch (Exception ex) {                
    if (ex is CommunicationException || ex is SystemException) {
        //handle it
    }
    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.

openshac
  • 4,966
  • 5
  • 46
  • 77
Maniero
  • 10,311
  • 6
  • 40
  • 85
  • 11
    As the up votes reflect, this is a better answer to the question. The accepted answer correctly addresses the code sample given but does not answer the question asked. – reads0520 Sep 21 '17 at 13:32
29

In fact, you could catch only SystemException and it would handle CommunicationException too, because CommunicationException is derived from SystemException

catch (SystemException se) {
   ... //this handles both exceptions
}
William Callahan
  • 630
  • 7
  • 20
archil
  • 39,013
  • 7
  • 65
  • 82
12

Unfortunately, there is no way. The syntax you used is invalid and a fall through like in a switch-statement isn't possible either. I think you need to go with the private method.

A little hacky work-around would be something like this:

var exceptionHandler = new Action<Exception>(e => { /* your three lines */ });
try
{
    // code that throws
}
catch(CommuncationException ex)
{
    exceptionHandler(ex);
}
catch(SystemException ex)
{
    exceptionHandler(ex);
}

You need to decide for yourself if this makes any sense.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • He doesn't want to do that :p – Gerrie Schenck Apr 06 '11 at 08:35
  • Yeah, where did he specify that? ;-) He just doesn't want to create a private method because of the code overhead it creates. This overhead is greatly reduced in my sample. But anyway, my *main* answer is, that he just can't do what he wants to do... I don't provide him with a "solution" he already dismissed in his question. – Daniel Hilgarth Apr 06 '11 at 08:37
  • 1
    I know, just having a laugh :) – Gerrie Schenck Apr 06 '11 at 08:41
5

No, you can't do it that way. The only way i know of is to catch a generic Exception and then check what type it is:

try
{
   ...
}
catch(Exception ex)
{
   if(ex is CommunicationException || ex is SystemException)
   {
      ...
   }
   else
   {
     ... // throw; if you don't want to handle it
   }
}
alexn
  • 57,867
  • 14
  • 111
  • 145
3

What about

try {


...
}

catch (CommunicationException ce) {
   HandleMyError(ce);
}

catch {SystemExcetion se) {
   HandleMyError(se);
}

private void HandleMyError(Exception ex)
{
// handle your error
}
Gerrie Schenck
  • 22,148
  • 20
  • 68
  • 95
3

Possible Duplicate of

Catch multiple exceptions at once?

I quote the answer here:

 catch (Exception ex)            
       {                
           if (ex is FormatException ||
               ex is OverflowException)
           {
               WebId = Guid.Empty;
               return;
           }
           else
           {
               throw;
           }
       }
Community
  • 1
  • 1
Marshal
  • 6,551
  • 13
  • 55
  • 91
  • I don't agree with the solution provided in that question for the same reason I don't support alexn's answer. It is indeed the same answer as alexn already gave... – Daniel Hilgarth Apr 06 '11 at 08:32
  • @Daniel: Hmmm..nice to know that it changes the call stack and might not work properly. – Marshal Apr 06 '11 at 08:36
  • It is important in this solution that it re-throws all the rest-type exceptions! – florien Oct 28 '17 at 18:14
2

Dragging this one up from the depths of history as it happened to pop up in some search results.

With the advent of C# 7.0 (which arrived in 2017 with VS2017, .net framework 4.7 and dotnet core 2.0) you can now do things like this:

try {
   ...
}
catch (Exception e) when (e is CommunicationException || e is SystemException) {
   ...
}
Rook
  • 5,734
  • 3
  • 34
  • 43
1

Since you're doing the same for both type of exceptions, you could just go:

try
{
    //do stuff
}
catch(Exception ex)
{
    //normal exception handling here
}

Only catch explicit Exception types if you need to do something unique for it.

tobias86
  • 4,979
  • 1
  • 21
  • 30