try / catch / throw和try / catch(e)/ throw e的区别
有什么区别
try { } catch { throw; }
和
try { } catch(Exception e) { throw e;}
?
而我应该什么时候使用一个或另一个?
build设
try { ... } catch () { ... } /* You can even omit the () here */ try { ... } catch (Exception e) { ... }
是类似的,都将捕获在try
块内引发的每个exception(除非你只是用这个来loggingexception,应该避免 )。 现在看看这些:
try { ... } catch () { /* ... */ throw; } try { ... } catch (Exception e) { /* ... */ throw; } try { ... } catch (Exception e) { /* ... */ throw e; }
第一个和第二个try-catch块是完全一样的东西,他们只是重新抛出当前的exception,而这个exception将保持其“源”和堆栈跟踪。
第三个try-catch块是不同的。 当它抛出exception时,它会改变源和堆栈的跟踪,这样看起来这个exception是从这个方法抛出的,就是从包含该try-catch块的方法中throw e
。
你应该使用哪一个? 这真的取决于每个案例。
假设你有一个带有.Save()
方法的Person
类,它将它保存到数据库中。 假设您的应用程序在某处执行了Person.Save()
方法。 如果你的DB拒绝保存Person,那么.Save()
会抛出exception。 在这种情况下,你应该使用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作为抛出新的exception的“内部exception”。 所以,当你检查这个InvalidPersonException时,堆栈跟踪将包含信息回到Save方法(这可能足以解决问题),但是如果你需要的话,你仍然可以访问原始exception。
最后一句话,当你期待一个exception时,你应该真的捕获到一个特定的exception,而不是一个普通的Exception
,也就是说,如果你期待InvalidPersonException,你应该更喜欢:
try { ... } catch (InvalidPersonException e) { ... }
至
try { ... } catch (Exception e) { ... }
祝你好运!
首先保留堆栈跟踪,而第二个重置它。 这意味着如果使用第二种方法,则exception的堆栈跟踪将始终从此方法开始,并且您将失去原始exception跟踪,这对于读取exception日志的人来说可能是灾难性的,因为他将永远不会找出exception的原因。
第二种方法可能是有用的,当你想添加额外的信息到堆栈跟踪,但它是这样使用:
try { // do something } catch (Exception ex) { throw new Exception("Additional information...", ex); }
有一个博客文章讨论了差异。
你应该使用
try { } catch(Exception e) { throw }
如果你想在抛出exception之前做一些事情(例如logging日志)。 孤独的投掷保存堆栈跟踪。
无参数catch和catch(Exception e)
之间的区别是你得到一个exception的引用。 从框架版本2中,非托pipe的exception被包装在一个托pipe的exception中,所以无参数的exception对任何东西都不再有用。
throw;
之间的区别throw;
throw e;
第一个用于重新抛出exception,第二个用于抛出新创build的exception。 如果您使用第二个重新抛出exception,它会将它视为一个新的exception,并将其最初抛出的所有堆栈信息replace掉。
所以,你不应该使用问题中的任何一种select。 你不应该使用无参数的catch,而应该使用throw;
重新抛出exception。
而且,在大多数情况下,对于所有exception,您应该使用比基类更具体的exception类。 你应该只捕捉你预期的例外。
try { ... } catch (IOException e) { ... throw; }
如果要在重新抛出exception时添加任何信息,则会创build一个具有原始exception的新exception作为内部exception来保留所有信息:
try { ... } catch (IOException e) { ... throw new ApplicationException("Some informative error message", e); }