重新投掷参数少捕获和没有做任何事情之间的区别?

假设我在两个不同的程序集中有以下两个类:

//in assembly A public class TypeA { // Constructor omitted public void MethodA { try { //do something } catch { throw; } } } //in assembly B public class TypeB { public void MethodB { try { TypeA a = new TypeA(); a.MethodA(); } catch (Exception e) //Handle exception } } } 

在这种情况下,MethodA中的try-catch只是提升exception,但并没有真正处理它。 在MethodA中使用try-catch是否有任何优势? 换句话说,这种try-catch块之间是否存在差异而根本不使用它?

在您的示例中,没有任何优势。 但有些情况下,最好只是冒出一个特定的例外。

  public void Foo() { try { // Some service adapter code // A call to the service } catch (ServiceBoundaryException) { throw; } catch (Exception ex) { throw new AdapterBoundaryException("some message", ex); } } 

这使您可以轻松识别发生exception的边界。在这种情况下,您需要确保仅针对边界特定的代码抛出边界exception。

是,有一点不同。 当你捕获exception时,.NET假定你将以某种方式处理它,堆栈被解开直到执行catch的函数。

如果你没有捕获它将最终作为未处理的exception,它将调用某种诊断(如调试器或exception记录器),完整堆栈及其在实际故障点的状态将可用于检查。

因此,如果您抓住然后重新抛出未在其他地方处理的exception,则会抢断诊断工具,了解实际发生的实际情况。

按原样,第一种选择似乎是一种糟糕的(或者应该是“无用的”?)的想法。 但是,很少这样做。 通常在两个条件下从Catch块中重新抛出exception:

一个。 您想要检查为数据生成的exception并有条件地将其冒泡到堆栈中。

 try { //do something } catch (Exception ex) { //Check ex for certain conditions. if (ex.Message = "Something bad") throw ex; else //Handle the exception here itself. } 

湾 组件内发生了不可接受的情况,并且需要将此信息传递给调用代码(通常通过附加一些其他有用信息或将其完全包装在另一个exception类型中)。

 try { //do something } catch (StackOverflowException ex) { //Bubble up the exception to calling code //by wrapping it up in a custom exception. throw new MyEuphemisticException(ex, "Something not-so-good just happened!"); } 

只是重新抛出是没有意义的 – 就像你没有做任何事情一样。

然而,当你真正做某事时它会变得有用 – 最常见的是记录exception。 你也可以改变你class级的状态。

使用代码就像你为MethodA编写代码一样,没有区别。 所有这一切都会耗尽处理器周期。 但是,如果有必须释放的资源,以这种方式编写代码会有一个优势。 例如

 Resource r = GetSomeResource(); try { // Do Something } catch { FreeSomeResource(); throw; } FreeSomeResource(); 

然而,这样做是没有意义的。 改为使用finally块会更好。

永远不要做选项A.正如安东所说,它会占用堆栈的痕迹。 JaredPar的例子也吃掉了堆栈跟踪。 更好的解决方案是:

 SomeType* pValue = GetValue(); try { // Do Something } finally { delete pValue; } 

如果您在C#中有需要发布的东西,例如FileStream,您有以下两种选择:

 FileStream stream; try { stream = new FileStream("C:\\afile.txt"); // do something with the stream } finally { // Will always close the stream, even if there are an exception stream.Close(); } 

或者更干净:

 using (FileStream stream = new FileStream("c:\\afile.txt")) { // do something with the stream } 

使用语句将在完成或关闭exception时处理(并关闭)流。

当你捕获并抛出时,它允许你在throw线上设置断点。

可以使用重新抛出exception将其封装到一般exception中,例如……考虑以下示例。

 public class XmlException: Exception{ .... } public class XmlParser{ public void Parse() { try{ .... } catch(IOException ex) { throw new XmlException("IO Error while Parsing", ex ); } } } 

这比分类exception有好处。 这就是aspx文件处理程序和许多其他系统代码执行exception封装的方式,它决定了它们到堆栈的方式及其逻辑流程。

程序集A – 尝试catch – block对我没有任何意义。 我相信如果你不打算处理exception,那你为什么要抓住那些例外呢……无论如何都会被抛到一个新的水平。

但是,如果你正在创建一个中间层API或类似的东西,并在该层中处理exception(因此吃掉exception)没有意义,那么你可以抛出自己的层ApplicationException。 但肯定重新抛出同样的例外是没有意义的。

由于这些类在2个不同的程序集中,您可能希望o只是捕获exception以进行记录,然后将其返回给调用者,以便它可以按照它认为合适的方式处理它。 throw而不是throw ex将保留有关exception发生位置的上下文信息。 当你的程序集是一个API /框架时,这可以certificate是有用的,除非它有意义,否则你应该永远不会吞下exception,但如果将它记录到例如事件日志中,则有助于解决问题。

仅当您可以捕获可在MethodA()中处理的特定exception时(例如:日志记录),您才可以在方法A中使用try {} catch(ex){}块。

另一个选项是使用InnerException属性链接exception并将其传递给调用者。 这个想法不会杀死堆栈跟踪。