try / catch / throw和try / catch(e)/ throw e之间的区别

时间:2009-11-08 17:18:15

标签: c# exception-handling

之间有什么区别
try { }
catch
{ throw; }

try { }
catch(Exception e)
{ throw e;}

我应该何时使用其中一种?

4 个答案:

答案 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);
}