使用它时是否相同:
catch(Exception e)
{
throw new Exception("some Exception", e);
}
和此:
catch(Exception e)
{
throw new Exception("some Exception", e.InnerException);
}
或者我错过了什么?
答案 0 :(得分:5)
在第二个示例中,您将丢弃已捕获的异常,而是使用其内部异常。您通常会在第一个示例中编写代码。
在第一种情况下,捕获的异常(e
)成为您抛出的新异常的InnerException
:
catch(Exception e)
{
throw new Exception("some Exception", e);
}
在第二种情况下,您使用InnerException
的{{1}},e
的数据丢失了:
e
答案 1 :(得分: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);
}
答案 2 :(得分:2)
有三种方法可以重新抛出异常:
catch (Exception ex)
{
throw;
}
抛出原始异常并保留原始堆栈跟踪。
catch (Exception ex)
{
throw ex;
}
抛出原始异常,但原始堆栈跟踪丢失。堆栈跟踪现在将此行显示为异常的发起者。
catch (Exception ex)
{
throw new Exception("...", ex);
}
引发新的异常,但保留原始异常及其堆栈跟踪作为新异常的InnerException
。
第一种情况非常有用,您需要清理失败但不成功。如果在两种情况下都需要清理,则使用finally子句,而不是catch子句。或者你只是想记录这里发生的异常并让调用者处理它。
第二种情况根本没用。你为什么要隐藏堆栈跟踪?可能有一些罕见的情况,这是有用的,但我不知道。
当您想要返回单一类型的异常(或类型系列)时,最常使用第三种情况。例如,您是一个文本解析方法,并且您希望将所有(非致命)异常转换为ParseException(或其他),这会提供其他详细信息,例如发生异常的文本中的行号。
在您提供的第二个示例中,捕获的异常将被完全丢弃。生成一个新异常,原始异常的InnerException成为此新异常的InnerException。我可以想象没有剥离中间异常会有用的情况。