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

Kar*_*rim 101 c# exception-handling

有什么区别

try { }
catch
{ throw; }
Run Code Online (Sandbox Code Playgroud)

try { }
catch(Exception e)
{ throw e;}
Run Code Online (Sandbox Code Playgroud)

什么时候应该使用其中一个?

Bru*_*eis 147

结构

try { ... }
catch () { ... } /* You can even omit the () here */

try { ... }
catch (Exception e) { ... }
Run Code Online (Sandbox Code Playgroud)

两者都类似,因为它们都会捕获块内抛出的每个异常try(并且,除非您只是使用它来记录异常,否则应该避免).现在看看这些:

try { ... }
catch ()
{
    /* ... */
    throw;
}

try { ... }
catch (Exception e)
{
    /* ... */
    throw;
}

try { ... }
catch (Exception e)
{
    /* ... */
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

第一个和第二个try-catch块完全相同,只是重新抛出当前异常,该异常将保持其"源"和堆栈跟踪.

第三个try-catch块是不同的.当它抛出异常时,它将更改源和堆栈跟踪,以便从throw e包含该try-catch块的方法的那一行开始,从该方法中抛出异常.

你应该使用哪一个?这实际上取决于每个案例.

假设您有一个Person具有.Save()将其持久保存到数据库中的方法的类.假设您的应用程序在Person.Save()某处执行该方法.如果您的DB拒绝保存Person,.Save()则会抛出异常.你应该使用throwthrow e在这种情况下?这得看情况.

我更喜欢做的是:

try {
    /* ... */
    person.Save();
}
catch(DBException e) {
    throw new InvalidPersonException(
       "The person has an invalid state and could not be saved!",
       e);
}
Run Code Online (Sandbox Code Playgroud)

这应该将DBException作为抛出的新异常的"内部异常".因此,当您检查此InvalidPersonException时,堆栈跟踪将包含返回Save方法的信息(这可能足以解决问题),但如果需要,您仍然可以访问原始异常.

作为最后的评论,当你期待一个异常时,你应该真正捕获一个特定的异常,而不是一般的Exception,即,如果你期望InvalidPersonException你应该更喜欢:

try { ... }
catch (InvalidPersonException e) { ... }
Run Code Online (Sandbox Code Playgroud)

try { ... }
catch (Exception e) { ... }
Run Code Online (Sandbox Code Playgroud)

祝好运!


Dar*_*rov 32

第一个保留堆栈跟踪,而第二个重置它.这意味着如果使用第二种方法,异常的堆栈跟踪将始终从此方法开始,您将丢失原始异常跟踪,这对于读取异常日志的人来说可能是灾难性的,因为他永远不会找到异常的原始原因.

当您想要向堆栈跟踪添加其他信息时,第二种方法可能很有用,但它的使用方式如下:

try
{
    // do something
}
catch (Exception ex)
{
    throw new Exception("Additional information...", ex);
}
Run Code Online (Sandbox Code Playgroud)

有一篇博客文章讨论了这些差异.


Otá*_*cio 6

你应该用

try { }
catch(Exception e)
{ throw }
Run Code Online (Sandbox Code Playgroud)

如果你想在重新抛出它之前对异常做一些事情(例如记录日志).孤独的投掷保留了堆栈的痕迹.

  • 正如Darin指出的那样,"throw e"将重置堆栈跟踪. (3认同)

Guf*_*ffa 5

无参数catch和a之间的区别catch(Exception e)是您可以引用该异常。从框架版本2开始,非托管异常包装在托管异常中,因此无参数异常不再对任何事物都有用。

throw;和之间的区别throw e;是,第一个用于引发异常,第二个用于引发新创建的异常。如果使用第二个异常抛出异常,它将把它当作新异常对待,并替换最初抛出异常时的所有堆栈信息。

因此,您不要在问题中使用任何一种替代方法。您不应使用无参数捕获,而应使用它throw;来抛出异常。

同样,在大多数情况下,对于所有异常,应使用比基类更具体的异常类。您应该只捕获预期的异常。

try {
   ...
} catch (IOException e) {
   ...
   throw;
}
Run Code Online (Sandbox Code Playgroud)

如果要在引发异常时添加任何信息,请创建一个新异常,并将原始异常作为内部异常保留所有信息:

try {
   ...
} catch (IOException e) {
   ...
   throw new ApplicationException("Some informative error message", e);
}
Run Code Online (Sandbox Code Playgroud)