捕获异常,添加数据并重新抛出它

Seb*_*zus 20 c# exception

我有以下代码:

try
{
   OnInitialize();
}
catch (PageObjectLifecycleException exception)
{
   exception.OldLifecycleState = CurrentLifecycleState;
   exception.RequestedLifecycleState = LifecycleState.Initialized;
   throw exception;
}
Run Code Online (Sandbox Code Playgroud)

我捕获一个异常,向它添加更多数据,然后重新抛出它.Resharper警告我(正确)可能需要重新抛出并建议将其更改为:

throw;
Run Code Online (Sandbox Code Playgroud)

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

编辑:回应"试一试"评论:我是C#的新手,来自C++.在C++中,你经常会在这样的角落情况下发现未定义的行为,我感兴趣的是我想要的是它是如何正式工作的.

Men*_*gis 27

您可以将额外信息添加到数据中并重新抛出异常,throw以便保持其原始形式和callstack

try
{
   ...
}
catch (PageObjectLifecycleException exception)
{
   exception.Data.Add("additional data", "the additional data");
   throw;
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案,这就是"数据"的用途.只要有人防范密钥冲突,并记住,字典中包含的任何信息都是1)传播到调用链上,并且2)可以在此过程中进行修改,这是添加有用信息以简化调试的好方法. (4认同)

jam*_*wis 26

我知道已经选择了答案但是这里有关于这个主题的更多信息.

try {
    // code
}
catch(Exception e) {
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

编译成IL时,上面的代码将产生一个调用throw,将对已处理异常的引用作为参数传递.您可能已经意识到,您可以throw从代码中的任何位置进行调用以引发异常.

try {
    // code
}
catch(Exception e) {
    throw;
}
Run Code Online (Sandbox Code Playgroud)

编译成IL时上面的代码会产生一个调用rethrow.这是不同的,以throw作为rethrow用于发送信号,在该异常被处理该块出于某种原因决定不处理它,因此,责任应给予高阶catch块(下一个了).

rethrow方法保留当前调用堆栈跟踪,以便可以跟踪异常的来源.但是,该throw方法启动一个新的调用堆栈跟踪.一旦你理解了这两种方法的用途,我认为这是有道理的.

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

在您的示例中,我建议如果您需要向异常添加更多信息,您可以创建一个全新的异常并提升它.因此,您将使用throw exception;"exception"是包含额外信息和最初抛出的异常的新异常的方法.

希望有所帮助!

詹姆士


Kit*_*sto 10

它将抛出对修改后的异常的引用.

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