【发布时间】:2010-12-14 09:50:09
【问题描述】:
有什么区别
try { }
catch
{ throw; }
和
try { }
catch(Exception e)
{ throw e;}
?
我什么时候应该使用其中一种?
【问题讨论】:
标签: c# exception-handling
有什么区别
try { }
catch
{ throw; }
和
try { }
catch(Exception e)
{ throw e;}
?
我什么时候应该使用其中一种?
【问题讨论】:
标签: c# exception-handling
第一个保留堆栈跟踪,而第二个重置它。这意味着如果您使用第二种方法,异常的堆栈跟踪将始终从此方法开始,您将丢失原始异常跟踪,这对于阅读异常日志的人来说可能是灾难性的,因为他永远不会找到异常的原始原因.
当您想向堆栈跟踪添加其他信息时,第二种方法可能很有用,但它的使用方式如下:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
有一个blog post 讨论差异。
【讨论】:
throw 和throw e 是分开的。
结构
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() 方法。如果您的数据库拒绝保存 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) { ... }
祝你好运!
【讨论】:
无参数 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);
}
【讨论】:
你应该使用
try { }
catch(Exception e)
{ throw }
如果您想在重新抛出异常之前对其进行处理(例如记录)。单独的 throw 会保留堆栈跟踪。
【讨论】: