2012-02-27 65 views
16

我有以下代码:捕获异常,添加数据,并重新抛出

try 
{ 
    OnInitialize(); 
} 
catch (PageObjectLifecycleException exception) 
{ 
    exception.OldLifecycleState = CurrentLifecycleState; 
    exception.RequestedLifecycleState = LifecycleState.Initialized; 
    throw exception; 
} 

我捕捉异常,更多的数据添加到它,并重新抛出。 ReSharper的警告我(正确地)一个重新抛出可能是打算和建议其更改为:

throw; 

但我想知道:这是否会正确地重新抛出修改异常或未经修改的原始一个?

编辑:作为对“尝试它并看到”的回应:我是C#的新手,来自C++。在C++中,你经常会在像这样的角落案例中发现未定义的行为,而且我感兴趣的是我想要的究竟是它的正式工作方式。

+6

试一试,看看会发生什么? – 2012-02-27 15:31:36

+0

它会重新引用任何引用指向 - 在你的情况下修改“异常”。 – 2012-02-27 15:31:59

回答

8

它会抛出引用修改的异常。

但是我不确定这是否是很好的编程风格。考虑创建一个新的异常并添加PageObjectLifecycleException作为它的内部异常。这样处理代码可以确定它是否具有正确的附加信息。

+0

我也是,这是一个真正的bug。例如,外部catch块阻止从较深层次传回的数据。 – 2012-02-27 15:44:16

+0

代码示例已简化。现有数据将不会被覆盖,只会提供一些缺失的附加数据。 – 2012-02-27 15:58:59

+0

@TonyHopkinson'Exception.Data'听起来好像是为了这个目的([here](https://msdn.microsoft.com/en-us/library/system.exception.data(v = vs.110) ).aspx)) – drzaus 2017-03-09 19:48:38

2

当前异常被重新抛出,虽然我不确定你的模式是一个非常好的和可维护的。

22

我知道答案已经被选中,但这里有更多关于这个主题的信息。

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

上述代码时编译成IL会产生到throw呼叫传递一个参考处理的异常作为参数。正如你可能知道的那样,你可以在代码中的任何地方调用throw来引发异常。

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

上面的代码在编译成IL时会产生一个调用rethrow。这与throw不同,因为rethrow用于表示由于某种原因决定不处理异常的块,因此应该将责任提供给更高阶的catch块(下一个块)。

rethrow方法保留当前调用堆栈跟踪,以便可以跟踪异常的来源。但是,throw方法会启动一个新的调用堆栈跟踪。我认为,一旦你明白这两种方法是用来做什么的,这是有道理的。

以我的经验,你使用throw exception;当你想抛出一个异常,出于某种原因(例如对象的验证失败),并且您已经执行了一些日志记录(即,当你仍然有后,你会在catch语句中使用throw;在将异常处理责任传递给更高级别之前,访问未通过验证的对象中的有用信息)。

在你的例子中,我会建议如果你需要添加更多的信息到异常,你有一个案例来创建一个全新的异常并提高它。所以你会使用throw exception;方法,其中“异常”是一个新的异常,包含额外的信息和最初抛出的异常。

希望有帮助!

詹姆斯

9

您可以添加额外的信息转换成数据,并再次引发与throw因此它保留了其原有形态异常和调用堆栈

try 
{ 
    ... 
} 
catch (PageObjectLifecycleException exception) 
{ 
    exception.Data.Add("additional data", "the additional data"); 
    throw; 
} 
+2

这应该是公认的答案,这就是'Data'的用途。只要有人防范关键冲突,并且记住字典中包含的任何信息都可以在呼叫链中传播,并且可以在此过程中进行修改,这是添加有用信息以便于调试的好方法。 – 2017-05-26 12:12:08

相关问题