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()
则会抛出异常.你应该使用throw
或throw 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)
有一篇博客文章讨论了这些差异.
你应该用
try { }
catch(Exception e)
{ throw }
Run Code Online (Sandbox Code Playgroud)
如果你想在重新抛出它之前对异常做一些事情(例如记录日志).孤独的投掷保留了堆栈的痕迹.
无参数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)