0

当我使用它时是否相同:

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

还有这个:

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

还是我错过了什么?

4

3 回答 3

5

在您的第二个示例中,您将丢弃捕获的异常并使用其内部异常。您通常会像在第一个示例中那样进行编码。

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

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

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

catch(Exception e)
{
   throw new Exception("some Exception", e.InnerException);
}
于 2012-06-07T18:20:20.763 回答
3

第一个例子一般来说更正确。当您由于另一个异常而引发新异常时,您应该将原始异常包含为新异常的内部异常。

但这并不是普遍正确的。在某些非常特殊的情况下,当您想要撤消另一个代码对实际错误的包装时,它可能很有用。

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);
}
于 2012-06-07T18:21:21.090 回答
2

重新抛出异常有三种方式:

catch (Exception ex)
{
    throw;
}

抛出原始异常并保留原始堆栈跟踪。

catch (Exception ex)
{
    throw ex;
}

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

catch (Exception ex)
{
    throw new Exception("...", ex);
}

抛出一个新异常,但保留原始异常及其堆栈跟踪作为InnerException新异常的。

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

第二种情况根本没有用。为什么要隐藏堆栈跟踪?可能有一些罕见的情况,这是有用的,但我不知道。

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

在您提供的第二个示例中,被捕获的异常被完全丢弃。产生了一个新的异常,原来异常的 InnerException 变成了这个新异常的 InnerException。我可以想象没有任何场景可以剥离中间异常。

于 2012-06-07T18:33:47.143 回答