开发者

C# Exception Handling Fall Through [duplicate]

开发者 https://www.devze.com 2022-12-12 09:40 出处:网络
This question already has answers here: Closed 10 years ago. Possible Duplicate: Catch multiple Exceptions at once?
This question already has answers here: Closed 10 years ago.

Possible Duplicate:

Catch multiple Exceptions at once?

Is there any way in C# to easily achieve the following pseduo-code:

try
{
...
}
catch ( ExceptionTypeA, ExceptionTypeB, ExceptionTypeC as ex)
{
... same code for all threw
}
开发者_如何转开发

Or

try
{
...
}
catch ( ExceptionTypeA ex )
catch ( ExceptionTypeB ex )
catch ( ExceptionTypeC ex )
{
... same code for all exceptions of A, B or C
}

I guess what I'm saying would be great would be fall-through on exception types.


The problem with the syntax as mentioned (with an ex) is: what properties/members should ex have? Different exception types are not necessarily compatible, unless there is inheritance involved (in which case, catch the least-derived that you care about).

The only current option is to just use Exception ex (or similar) and check (is/as) inside the handler.

Or; refactor the common code into a method that can be used by all three?


In short, no. I can think of two three alternatives:

Catch each exception, and call a common method:

try
{
   // throw
}
catch ( ExceptionTypeA ex )
{
     HandleException();
}
catch ( ExceptionTypeB ex )
{
     HandleException();
}
catch ( ExceptionTypeC ex )
{
     HandleException();
}

void HandleException()
{
}

Or catch everything, and use an if statement on the type:

try
{
   // throw
}
catch (Exception ex)
{
   if (ex is ArgumentException || ex is NullReferenceException || ex is FooException)
   {
      // Handle
   }
   else
   {
      throw
   }
}

EDIT: OR, you could do something like this:

List<Type> exceptionsToHandle = new List<Type>{ typeof(ArgumentException), typeof(NullReferenceException), typeof(FooException) };

try
{
   // throw
}
catch (Exception ex)
{
   if (exceptionsToHandle.Contains(ex.GetType()))
   {
      // Handle
   }
   else
   {
      throw
   }
}


You can catch a general exception and then examine the type, e.g.:

catch (Exception ex)            
   {                
      if (ex is ExceptionTypeA ||
          ex is ExceptionTypeB )
           {
               /* your code here */
           }
       else
           {
               throw;
           }
    }

Edit: in line with other answers I'd be looking to clarify what's going on by pulling out a method - but rather than individual catches and a common method, I'd probably introduce a method to clarify what the contents of the if statement is doing. So instead of

if (ex is ExceptionTypeA || ex is ExceptionTypeB )

it'd become something like:

if (IsRecoverableByDoingWhatever(ex))

which I think would clarify the intent more than pulling out the handler code (although that might be useful to do too).


Wrap the repetitive code in a method.

try
{
...
}
catch ( ExceptionTypeA ex )
{
     DoSomething();
}
catch ( ExceptionTypeB ex )
{
     DoSomething();
}
catch ( ExceptionTypeC ex )
{
     DoSomething();
}
catch ( Exception ex )
{
     DoTheDefaultSomething();
}


If you need to use some variables from the scope of try, use a nested function. That is, a lambda or an anonymous delegate:

int x = ...;
Action<Exception> handler = delegate(Exception ex)
{
    // Same code for all exceptions of A, B or C.
    // You can use variable x here too.
};    

try
{
...
}
catch (ExceptionTypeA ex) { handler(ex); }
catch (ExceptionTypeB ex) { handler(ex); }
catch (ExceptionTypeC ex) { handler(ex); }


If you have access to the code that define the custom exceptions, one possible solution is:

Create a custom exception type.

public abstract class CustomException : Exception
{
        //Do some stuff here
}

Then make all your custom exceptions derive from this base type:

public class MyException1 : CustomException
{
        // Do some stuff here
}

public class MyException2 : CustomException
{
    // Do some stuff here
}

You are done. So now, all you need in your client code is to catch the custom exception base class.

try
{
     //Do something that throws a custom exception
}
catch (CustomException ex)
{
     // Do some shared behavior for all the custom exceptions
}   


You would derive TypeA, B, C from a common base class if this is reasonable. And catch the base class exception.


Not a clean way. You could just catch System.Exception and then check the type at runtime, ie.

try
{
...
}
catch (System.Exception ex)
{
   if (ex is ExceptionTypeA or ExceptionTypeB or ExceptionTypeC)
   {
       ... same code ...
   }
   else
       throw;
}

... but this is pretty ugly. It would be nicer to, as João Angelo said, have separate catch blocks for each exception type, but call a common method in each of them.

0

精彩评论

暂无评论...
验证码 换一张
取 消