C异常处理失败

C# Exception Handling Fall Through

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Catch multiple Exceptions at once?

C中是否有任何方法可以轻松实现以下psedoo代码:

1
2
3
4
5
6
7
8
try
{
...
}
catch ( ExceptionTypeA, ExceptionTypeB, ExceptionTypeC as ex)
{
... same code for all threw
}

1
2
3
4
5
6
7
8
9
10
try
{
...
}
catch ( ExceptionTypeA ex )
catch ( ExceptionTypeB ex )
catch ( ExceptionTypeC ex )
{
... same code for all exceptions of A, B or C
}

我想我要说的是非常好的,会在异常类型上失败。


前面提到的语法问题(对于ex)是:ex应该具有哪些属性/成员?不同的异常类型不一定是兼容的,除非涉及继承(在这种情况下,捕获您关心的派生最少的类型)。

唯一的当前选项是只在处理程序中使用Exception ex(或类似)和check(is/as)。

或者,将公共代码重构为三者都可以使用的方法?


简言之,没有。我可以想到twothree alternative:

捕获每个异常,并调用一个公共方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try
{
   // throw
}
catch ( ExceptionTypeA ex )
{
     HandleException();
}
catch ( ExceptionTypeB ex )
{
     HandleException();
}
catch ( ExceptionTypeC ex )
{
     HandleException();
}

void HandleException()
{
}

或者捕获所有内容,并对类型使用if语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try
{
   // throw
}
catch (Exception ex)
{
   if (ex is ArgumentException || ex is NullReferenceException || ex is FooException)
   {
      // Handle
   }
   else
   {
      throw
   }
}

编辑:或者,您可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
   }
}


您可以捕获一般异常,然后检查类型,例如:

1
2
3
4
5
6
7
8
9
10
11
12
catch (Exception ex)            
   {                
      if (ex is ExceptionTypeA ||
          ex is ExceptionTypeB )
           {
               /* your code here */
           }
       else
           {
               throw;
           }
    }

编辑:根据其他答案,我希望通过拉出一个方法来澄清正在发生的事情——但我可能会引入一种方法来澄清if语句的内容,而不是单个捕获和常见方法。因此,而不是

1
if (ex is ExceptionTypeA || ex is ExceptionTypeB )

它会变得像:

1
if (IsRecoverableByDoingWhatever(ex))

我认为,这不仅仅是拉出处理程序代码的意图(尽管这也可能是有用的)。


用方法包装重复的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try
{
...
}
catch ( ExceptionTypeA ex )
{
     DoSomething();
}
catch ( ExceptionTypeB ex )
{
     DoSomething();
}
catch ( ExceptionTypeC ex )
{
     DoSomething();
}
catch ( Exception ex )
{
     DoTheDefaultSomething();
}


如果需要使用try范围内的一些变量,请使用嵌套函数。也就是说,lambda或匿名委托:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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); }

如果您可以访问定义自定义异常的代码,一个可能的解决方案是:

创建自定义异常类型。

1
2
3
4
public abstract class CustomException : Exception
{
        //Do some stuff here
}

然后使所有自定义异常都从此基类型派生:

1
2
3
4
5
6
7
8
9
public class MyException1 : CustomException
{
        // Do some stuff here
}

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

你完了。因此,现在,您在客户机代码中所需要的只是捕获自定义异常基类。

1
2
3
4
5
6
7
8
try
{
     //Do something that throws a custom exception
}
catch (CustomException ex)
{
     // Do some shared behavior for all the custom exceptions
}


不是一条干净的路。您只需捕获Stase.ExtExchange,然后在运行时检查类型,即。

1
2
3
4
5
6
7
8
9
10
11
12
13
try
{
...
}
catch (System.Exception ex)
{
   if (ex is ExceptionTypeA or ExceptionTypeB or ExceptionTypeC)
   {
       ... same code ...
   }
   else
       throw;
}

…但这很难看。像乔那样更好?o angelo说,每个异常类型都有单独的catch块,但是在每个异常类型中调用一个公共方法。


如果这是合理的,您可以从一个公共的基类派生类型A、B、C。并捕获基类异常。