当我使用它时是否相同:
catch(Exception e)
{
throw new Exception("some Exception", e);
}
还有这个:
catch(Exception e)
{
throw new Exception("some Exception", e.InnerException);
}
还是我错过了什么?
当我使用它时是否相同:
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);
}
在第二种情况下,您使用的是InnerException
of e
,并且来自的数据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。我可以想象没有任何场景可以剥离中间异常。