异常构造函数类

本文关键字:构造函数 异常 | 更新日期: 2023-09-27 18:36:27

当我使用它时,它是一样的吗:

catch(Exception e)
{
    throw new Exception("some Exception", e);
}

而这个:

catch(Exception e)
{
   throw new Exception("some Exception", e.InnerException);
}

还是我错过了什么?

异常构造函数类

在第二个示例中,您将丢弃捕获的异常,而是使用其内部异常。您通常会像第一个示例中一样编写代码。

在第一种情况下,捕获的异常 ( e ) 成为您抛出的新异常的InnerException

catch(Exception e)
{
    throw new Exception("some Exception", e);
}

在第二种情况下,您使用的是 eInnerException,并且来自e的数据将丢失:

catch(Exception e)
{
   throw new Exception("some Exception", e.InnerException);
}

第一个例子一般来说更正确。 当您抛出一个新异常作为另一个异常的结果时,您应该将原始异常作为新异常的内部异常包含在内。

不过,这并非普遍正确。 在某些非常特殊的情况下,它很有用,因为您希望撤消另一个代码对真正错误的包装。

try {
  // some reflection call 
} catch (TargetInvocationException e) {
  // Reduce the layers of data a developer has to dig through by using the real
  // exception when I re-wrap
  throw new MyException("some message", e.InnerException);
}

三种方法可以重新引发异常:

catch (Exception ex)
{
    throw;
}

引发原始异常,并保留原始堆栈跟踪。

catch (Exception ex)
{
    throw ex;
}

引发原始异常,但原始堆栈跟踪丢失。堆栈跟踪现在将此行显示为异常的发起方。

catch (Exception ex)
{
    throw new Exception("...", ex);
}
引发新异常

,但保留原始异常及其堆栈跟踪作为新异常的InnerException

第一种情况很有用,您需要清理失败而不是成功。如果你需要在这两种情况下进行清理,你将使用 finally 子句,而不是 catch 子句。或者,您只想记录此处发生的异常,并让调用方处理它。

第二种情况根本没有用处。为什么要隐藏堆栈跟踪?在极少数情况下,这可能是有用的,但我知道没有。

当您想要返回单一类型的异常(或类型系列)时,最常使用第三种情况。例如,您是一个文本解析方法,您希望将所有(非致命)异常转换为 ParseException(或其他任何异常),从而提供其他详细信息,例如发生异常的文本中的行号。

在您提供的第二个示例中,捕获的异常将被完全丢弃。将生成一个新的异常,并且原始异常的 InnerException 将成为此新异常的 InnerException。我无法想象剥离中间异常的任何情况都是有用的。