C#异常处理失败
可能重复:C#异常处理失败,c#,exception-handling,C#,Exception Handling,可能重复: 在C#中是否有任何方法可以轻松实现以下PSEDOO代码: try { ... } catch ( ExceptionTypeA, ExceptionTypeB, ExceptionTypeC as ex) { ... same code for all threw } 或 我想我要说的是,在异常类型上会失败。前面提到的语法(使用ex)的问题是:ex应该有哪些属性/成员?不同的异常类型不一定是兼容的,除非涉及到继承(在这种情况下,捕获您关心的最不派生的异常类型) 当前唯一的选项是只
在C#中是否有任何方法可以轻松实现以下PSEDOO代码:
try
{
...
}
catch ( ExceptionTypeA, ExceptionTypeB, ExceptionTypeC as ex)
{
... same code for all threw
}
或
我想我要说的是,在异常类型上会失败。前面提到的语法(使用
ex
)的问题是:ex
应该有哪些属性/成员?不同的异常类型不一定是兼容的,除非涉及到继承(在这种情况下,捕获您关心的最不派生的异常类型)
当前唯一的选项是只使用Exception ex
(或类似选项)并在处理程序内检查(is
/as
)
或;将公共代码重构成一个三者都可以使用的方法 将重复代码包装到方法中
try
{
...
}
catch ( ExceptionTypeA ex )
{
DoSomething();
}
catch ( ExceptionTypeB ex )
{
DoSomething();
}
catch ( ExceptionTypeC ex )
{
DoSomething();
}
catch ( Exception ex )
{
DoTheDefaultSomething();
}
如果这是合理的,您可以从公共基类派生TypeA、B、C。并捕获基类异常。您可以捕获常规异常,然后检查类型,例如:
catch (Exception ex)
{
if (ex is ExceptionTypeA ||
ex is ExceptionTypeB )
{
/* your code here */
}
else
{
throw;
}
}
编辑:与其他答案一样,我希望通过拉出一个方法来澄清发生了什么,但我可能会引入一个方法来澄清if语句的内容在做什么,而不是单独捕获和普通方法。所以不是
if (ex is ExceptionTypeA || ex is ExceptionTypeB )
它会变成这样:
if (IsRecoverableByDoingWhatever(ex))
我认为这比提取处理程序代码更能阐明目的(尽管这样做可能也很有用)。不是一种干净的方法。您可以捕获System.Exception,然后在运行时检查类型,即
try
{
...
}
catch (System.Exception ex)
{
if (ex is ExceptionTypeA or ExceptionTypeB or ExceptionTypeC)
{
... same code ...
}
else
throw;
}
。。。但这很难看。正如João Angelo所说,最好为每种异常类型使用单独的catch块,但在每种异常类型中调用一个通用方法。简言之,不。我可以想出两种或三种备选方法: 捕获每个异常,并调用一个通用方法:
try
{
// throw
}
catch ( ExceptionTypeA ex )
{
HandleException();
}
catch ( ExceptionTypeB ex )
{
HandleException();
}
catch ( ExceptionTypeC ex )
{
HandleException();
}
void HandleException()
{
}
或捕获所有内容,并对类型使用if语句:
try
{
// throw
}
catch (Exception ex)
{
if (ex is ArgumentException || ex is NullReferenceException || ex is FooException)
{
// Handle
}
else
{
throw
}
}
编辑:或者,您可以执行以下操作:
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
}
}
List exceptionsToHandle=新列表{typeof(ArgumentException)、typeof(NullReferenceException)、typeof(footeexception)};
尝试
{
//扔
}
捕获(例外情况除外)
{
if(exceptionsToHandle.Contains(例如GetType()))
{
//处理
}
其他的
{
扔
}
}
如果您可以访问定义自定义异常的代码,一种可能的解决方案是:
创建自定义异常类型
public abstract class CustomException : Exception
{
//Do some stuff here
}
然后使您的所有自定义异常都从此基类型派生:
public class MyException1 : CustomException
{
// Do some stuff here
}
public class MyException2 : CustomException
{
// Do some stuff here
}
你完了。因此,现在,在客户端代码中所需要的只是捕获自定义异常基类
try
{
//Do something that throws a custom exception
}
catch (CustomException ex)
{
// Do some shared behavior for all the custom exceptions
}
如果需要使用
try
范围内的某些变量,请使用嵌套函数。即lambda或匿名委托:
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); }
intx=。。。;
操作处理程序=委托(异常示例)
{
//A、B或C的所有例外情况的代码相同。
//这里也可以使用变量x。
};
尝试
{
...
}
catch(ExceptionTypeA-ex){handler(ex);}
catch(ExceptionTypeB-ex){handler(ex);}
catch(ExceptionTypeC-ex){handler(ex);}
将通用代码提取到函数中不是一个选项?另请参见此处的解决方案:C#6方式:这里的问题是可以从DoTheDefaultSomething中访问变量的范围。@Nissan Fan:您是否建议DoTheDefaultSomething()应为DoTheDefaultSomething(ex)?不,更多的变量范围为Try。。。Catch部分的作用域是包含Try。。。在这种情况下,Catch部分将超出范围。这实际上是一个合理的请求,因为有时您确实希望捕获Derived1
和Derived2
,但不希望捕获Derived3
,因此您不能只捕获Base
,但您希望对这两个部分都做同样的事情。它在某种程度上是为Java7设计的,语法类似于catch(Derived1 | derived2ex)
,只为您提供最接近的公共基类型的成员,但他们在本版本中放弃了它。尽管如此,这将是对类型系统的一个有趣的补充。也许,但它与成本与效益的争论是一致的。简单地为公共逻辑创建一个方法有多难?根据它使用的范围try
中的数据量,创建这样一个方法的努力可以是瞬间的,也可以是现代的,从C#7开始,通过模式匹配在switch
语句中提供了下拉功能。CatchException ex
,并且在switch(ex){}
语句中,您可以这样做:case ArgumentException argEx:
;这种方法提供了OP请求的功能,并且与将详细的错误处理转移到单独方法的建议兼容。看见在C#8中,您甚至可以使用开关表达式来更简洁;看。@Daniel你应该加上这个作为例子的答案,IMO;我肯定会支持它(如果我注意到的话),这从来不是推荐的方法,而且语言也不是为这种方法设计的。然而,它仍然是唯一不需要重复代码的模式。您应该更新它以包括异常类型上的模式匹配。这使得模式变得更好。
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); }