为什么我的自定义异常包含在System.Exception中?

时间:2017-08-01 18:15:30

标签: c# exception exception-handling

我相信我正在遵循正确的过程来实现自定义异常,但异常到达包含在System.Exception中的catch块,因此我的自定义异常的处理不会执行。 / p>

我创建了自定义异常类(以下在线示例):

...
if (up == down)
{
    throw new MyCustomException("Things are topsy-turvy.");
}
...

我从堆栈中的较低点抛出异常:

try
{
    DoSomeStuff(();
}
catch (Exception ex)
{
    LogManager.Instance.LogException(ex);
    throw;
}
finally
{
    DoSomeCleanup();
}

异常是在中间try-catch中捕获的。我知道这种捕获日志记录是错误的做法,但是这个代码是在这个应用程序中调用的现有方法,并且对我的小改动进行回归测试整个应用程序并不是一个选择。无论如何,这个引发并不会导致问题:异常到达此catch已作为System.Exception包装我的自定义异常。

...
try
{
    CallAMethod();
}
catch MyCustomException(ex)
{
    LogManager.Instance.LogException(ex);
    ShowErrorMessage(ex.Message);
}
catch Exception(ex)
{
    throw ex;
}

我有代码在下一次赶上堆栈时捕获自定义异常。但异常作为包装自定义异常的System.Exception到达,因此我的自定义异常处理不会被执行。

resolve

我相信我投掷的例外情况不应该被包裹,所以我必须做错事。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

public class MyCustomException : Exception

该代码表示​​您的类正在扩展Exception类。因此,当您抛出它并使用Exception catch捕获它时,它将作为该基类保存。您始终可以将其强制转换回MyCustomException

如果通过换行,您的意思是将自定义异常作为内部异常包含在内,这可能是因为您重新抛出异常。

它也可能是你的第二组尝试捕获功能。我之前没有见过这种风格,所以它可能是有效的,但试着写成

catch(MyCustomException ex){
...
}

代替

答案 1 :(得分:1)

为什么?

异常处理程序将捕获或派生自指定异常类型的任何异常。

例如

catch (System.Exception e)
{
    //Handler
}

......会抓住一切。同时

catch (System.ApplicationException e)
{
    //Handler
}

...将捕获源自ApplicationException的所有异常。这包括所有这些:

Microsoft.JScript.NoContextException, Microsoft.JScript.ReturnOutOfFinally, System.Reflection.InvalidFilterCriteriaException, System.Reflection.TargetException, System.Reflection.TargetInvocationException, System.Reflection.TargetParameterCountException, System.Threading.WaitHandleCannotBeOpenedException

这正是你永远不应该抓住System.Exception的原因。它抓住了一切!

这也是异常处理程序按特定顺序声明为一般的原因 - 如果通用处理程序是第一个,则其他处理程序都不会触发。

如何修复

如果可以的话,摆脱catch (System.Exception)

解决方法

如果您无法摆脱catch (System.Exception)阻止,可以使用when filter,这样就会忽略您的自定义异常,如下所示:

catch (System.Exception e) when (!(e is MyCustomException))
{
    //Handler
}

答案 2 :(得分:0)

不是您的查询的答案,但通常,您的自定义异常应该包含这3个构造函数(可能您已经拥有它)

Exception best practices

  

在创建自己的异常类时至少使用三个常用构造函数:默认构造函数,接受字符串消息的构造函数,以及接受字符串消息和内部异常的构造函数。

这将允许您链接异常,即InnerException属性可以包含另一个异常对象,其InnerException可以包含另一个异常对象,依此类推。

此外,只有throw语句的处理程序是正确的方式(在大多数情况下),因为它preserve the stack trace info