C# try/catch/throw和try/catch(e)/throw e之间的区别
两者的区别是什么C# try/catch/throw和try/catch(e)/throw e之间的区别,c#,exception-handling,C#,Exception Handling,两者的区别是什么 try { } catch { throw; } 及 ? 什么时候应该使用一个或另一个?第一个保留堆栈跟踪,而第二个重置堆栈跟踪。这意味着,如果使用第二种方法,异常的堆栈跟踪将始终从该方法开始,并且您将丢失原始异常跟踪,这对于阅读异常日志的人来说可能是灾难性的,因为他永远不会找到异常的原始原因 当您希望向堆栈跟踪添加其他信息时,第二种方法可能很有用,但它的使用方式如下: try { // do something } catch (Exception ex) {
try { }
catch
{ throw; }
及
?
什么时候应该使用一个或另一个?第一个保留堆栈跟踪,而第二个重置堆栈跟踪。这意味着,如果使用第二种方法,异常的堆栈跟踪将始终从该方法开始,并且您将丢失原始异常跟踪,这对于阅读异常日志的人来说可能是灾难性的,因为他永远不会找到异常的原始原因 当您希望向堆栈跟踪添加其他信息时,第二种方法可能很有用,但它的使用方式如下:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
这里有一个讨论差异的论坛。您应该使用
try { }
catch(Exception e)
{ throw }
如果您想在重新抛出异常之前处理异常(例如日志记录)。孤注一掷保留堆栈跟踪。结构
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块是不同的。当它抛出异常时,它将更改源和堆栈跟踪,以便显示异常是从包含try-catch块的方法上的throw e
这一行抛出的
你应该用哪一种?这取决于每种情况
假设您有一个Person
类和一个.Save()
方法,该方法将把它持久化到数据库中。假设应用程序在某处执行Person.Save()
方法。如果数据库拒绝保存此人,则.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方法的信息(这可能足以解决问题),但如果需要,您仍然可以访问原始异常
最后一句话,当您预期出现异常时,您应该真正捕捉到一个特定的异常,而不是一般的异常
,也就是说,如果您预期出现InvalidPersonException,您应该选择:
try { ... }
catch (InvalidPersonException e) { ... }
到
祝你好运 无参数catch和
catch(异常e)
之间的区别在于您获得了对异常的引用。从FrameworkVersion2开始,非托管异常被包装在托管异常中,因此无参数异常对任何事情都不再有用
throw之间的差异代码>和抛出e代码>,第一个用于重新抛出异常,第二个用于抛出新创建的异常。如果使用第二个异常来重新抛出异常,它会将其视为新异常,并替换最初抛出异常的所有堆栈信息
所以,你不应该使用问题中的任何一个选项。您不应该使用无参数catch,而应该使用throw
以重新显示异常
此外,在大多数情况下,您应该为所有异常使用比基类更具体的异常类。您应该只捕获预期的异常
try {
...
} catch (IOException e) {
...
throw;
}
如果要在重新引发异常时添加任何信息,请创建一个新异常,将原始异常作为内部异常,以保留所有信息:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}
知道这些真是太好了!那么为什么要使用第二个呢?只使用第一个是否更好?第二个在需要检查特定异常时有用,比如OutOfRangeExtExcor——或者需要记录消息等。第一个似乎是通配符异常处理程序,类似于C++中的{{}} catch(…){}。戴维只适用于catch(Exchange E)部分。这与throw
vsthrow e
是分开的。如果我把这里的“throw”替换为“throw e”,会发生什么?
try {
...
} catch (IOException e) {
...
throw;
}
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}