之间有什么区别
try { }
catch
{ throw; }
和
try { }
catch(Exception e)
{ throw e;}
我应该何时使用其中一种?
答案 0 :(得分:140)
结构
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
类似的是,它们都会捕获try
块中抛出的每个异常(除非您只是使用它来记录异常,否则应该> )。现在看看这些:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
第一个和第二个try-catch块完全相同,只是重新抛出当前异常,该异常将保持其“源”和堆栈跟踪。
第三个try-catch块是不同的。当它抛出异常时,它将更改源和堆栈跟踪,以便从包含该try-catch块的方法的那一行throw e
开始显示该异常。
你应该使用哪一个?这实际上取决于每个案例。
假设您有一个Person
类,其.Save()
方法会将其保存到数据库中。假设您的应用程序在某处执行Person.Save()
方法。如果您的DB拒绝保存Person,则.Save()
将抛出异常。在这种情况下,您应该使用throw
还是throw e
?嗯,这取决于。
我更喜欢做的事情:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
这应该将DBException作为抛出的新异常的“内部异常”。因此,当您检查此InvalidPersonException时,堆栈跟踪将包含返回Save方法的信息(这可能足以解决问题),但如果需要,您仍然可以访问原始异常。
作为最后的评论,当你期待异常时,你应该真正捕获一个特定的异常,而不是一般的Exception
,即,如果你期望InvalidPersonException你应该更喜欢:
try { ... }
catch (InvalidPersonException e) { ... }
到
try { ... }
catch (Exception e) { ... }
祝你好运!
答案 1 :(得分:32)
第一个保留堆栈跟踪,而第二个重置它。这意味着如果使用第二种方法,异常的堆栈跟踪将始终从此方法开始,您将丢失原始异常跟踪,这对于读取异常日志的人来说可能是灾难性的,因为他永远不会找到异常的原始原因
当您想要向堆栈跟踪添加其他信息时,第二种方法可能很有用,但它的使用方式如下:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
有一篇博客post讨论了这些差异。
答案 2 :(得分:6)
你应该使用
try { }
catch(Exception e)
{ throw }
如果你想在重新抛出异常之前做一些事情(例如记录日志)。孤独的投掷保留了堆栈痕迹。
答案 3 :(得分:5)
无参数catch和catch(Exception e)
之间的区别在于您获得了对异常的引用。从框架版本2开始,非托管异常包含在托管异常中,因此无参数异常对任何内容都不再有用。
throw;
和throw e;
之间的区别在于第一个用于重新抛出异常,第二个用于抛出新创建的异常。如果您使用第二个重新抛出异常,它会将其视为新异常,并将所有堆栈信息替换为最初抛出异常的位置。
所以,你不要使用问题中的任何一个替代方案。您不应该使用无参数catch,并且应该使用throw;
来重新抛出异常。
此外,在大多数情况下,对于所有异常,您应该使用比基类更具体的异常类。您应该只捕获您预期的例外情况。
try {
...
} catch (IOException e) {
...
throw;
}
如果要在重新抛出异常时添加任何信息,可以创建一个新异常,将原始异常作为内部异常保留所有信息:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}