C# try/catch/throw 和 try/catch(e)/throw e 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1697216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:02:38  来源:igfitidea点击:

The difference between try/catch/throw and try/catch(e)/throw e

c#exception-handling

提问by Karim

What is the difference between

之间有什么区别

try { }
catch
{ throw; }

and

try { }
catch(Exception e)
{ throw e;}

?

?

And when should I use one or the other?

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

采纳答案by Bruno Reis

The constructions

建筑

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

try { ... }
catch (Exception e) { ... }

are similar in that both will catch everyexception thrown inside the tryblock (and, unless you are simply using this to log the exceptions, should be avoided). Now look at these:

相似之处在于两者都将捕获块内抛出的每个异常try(并且,除非您只是使用它来记录异常,否则应该避免)。现在看看这些:

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

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

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

The first and second try-catch blocks are EXACTLY the same thing, they simply rethrow the current exception, and that exception will keep its "source" and the stack trace.

第一个和第二个 try-catch 块完全相同,它们只是重新抛出当前异常,该异常将保留其“源”和堆栈跟踪。

The third try-catch block is different. When it throws the exception, it will change the source and the stack trace, so that it will appear that the exception has been thrown from this method, from that very line throw eon the method containing that try-catch block.

第三个 try-catch 块不同。当它抛出异常时,它将更改源和堆栈跟踪,因此看起来异常已从该方法抛出,从throw e包含该 try-catch 块的方法上的那一行开始。

Which one should you use? It really depends on each case.

你应该使用哪一个?这真的取决于每个案例。

Let's say you have a Personclass with a .Save()method that will persist it into a database. Let's say that your application executes the Person.Save()method somewhere. If your DB refuses to save the Person, then .Save()will throw an exception. Should you use throwor throw ein this case? Well, it depends.

假设您有一个Person带有.Save()方法的类,可以将它保存到数据库中。假设您的应用程序在Person.Save()某处执行该方法。如果您的数据库拒绝保存 Person,.Save()则将抛出异常。在这种情况下,您应该使用throw还是throw e?这要看情况。

What I prefer is doing:

我更喜欢做的是:

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

This should put the DBException as the "Inner Exception" of the newer exception being throw. So when you inspect this InvalidPersonException, the stack trace will contain info back to the Save method (that might be sufficient for you to solve the problem), but you still have access to the original exception if you need it.

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

As a final remark, when you are expectingan exception, you should really catch that one specific exception, and not a general Exception, ie, if you are expecting an InvalidPersonException you should prefer:

最后要说的是,当您期待异常时,您应该真正捕获该特定异常,而不是一般异常Exception,即,如果您期待 InvalidPersonException,您应该更喜欢:

try { ... }
catch (InvalidPersonException e) { ... }

to

try { ... }
catch (Exception e) { ... }

Good luck!

祝你好运!

回答by Darin Dimitrov

The first preserves the stack trace while the second resets it. This means that if you use the second approach the stack trace of the exception will always start from this method and you will lose the original exception trace which could be disastrous for someone reading exception logs as he will never find out the original cause of the exception.

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

The second approach might be useful when you want to add additional information to the stack trace but it is used like this:

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

try
{
    // do something
}
catch (Exception ex)
{
    throw new Exception("Additional information...", ex);
}

There's a blog postdiscussing the differences.

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

回答by Otávio Décio

You should use

你应该使用

try { }
catch(Exception e)
{ throw }

if you want to do something with the exception before re-throwing it (logging for example). The lonely throw preserves stack trace.

如果您想在重新抛出异常之前对其进行处理(例如记录)。孤独的抛出保留了堆栈跟踪。

回答by Guffa

The difference between a parameterless catch and a catch(Exception e)is that you get a reference to the exception. From framework version 2 unmanaged exceptions are wrapped in a managed exception, so the parameterless exception is no longer useful for anything.

无参数捕获和 a 之间的区别在于catch(Exception e)您获得对异常的引用。从框架版本 2 开始,非托管异常被包装在托管异常中,因此无参数异常不再对任何事情有用。

The difference between throw;and throw e;is that the first one is used to rethrow exceptions and the second one is used to throw a newly created exception. If you use the second one to rethrow an exception, it will treat it like a new exception and replace all stack information from where it was originally thrown.

和 的区别在于throw;throw e;第一个用于重新抛出异常,第二个用于抛出新创建的异常。如果您使用第二个重新抛出异常,它会将其视为新异常并替换最初抛出的所有堆栈信息。

So, you shold not use either of the alternatives in the question. You should not use the parameterless catch, and you should use throw;to rethrow an exception.

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

Also, in most cases you should use a more specific exception class than the base class for all exceptions. You should only catch the exceptions that you anticipate.

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

try {
   ...
} catch (IOException e) {
   ...
   throw;
}

If you want to add any information when rethrowing the exception, you create a new exception with the original exception as an inner exception to preservere all information:

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

try {
   ...
} catch (IOException e) {
   ...
   throw new ApplicationException("Some informative error message", e);
}