Rethrowing an exception in C#
我有一些代码可以捕获异常,回滚事务,然后重新引发异常。
1 2 3 4
| catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw exSys ;
} |
如果我使用这个代码,vs代码分析会发出警告说
Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.
如果我使用代码
1 2 3 4
| catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw;
} |
然后我得到警告说
The variable 'exSys' is declared but never used
我该如何解决这个问题?
编辑我试过这个方法,但不管用。System.Exception类需要额外的消息以及内部异常。如果我这样做,它将抛出一条新消息,覆盖来自原始异常的消息。我不想得到新的异常,我想用相同的消息抛出相同的异常。
1 2 3 4
| catch (System.Exception ex )
{
throw new System.Exception(ex );
} |
编辑
1 2 3 4
| catch (System.Exception ex )
{
throw new System.Exception("Test",ex );
} |
尝试过这种方法。然后使用throw new Exception("From inside");手动引发异常。现在,例如,消息返回"test"而不是"from inside"。我想保持"从内部"的信息不变。建议的更改将导致错误显示代码出现问题。:
- 使用throw exSys;。
- @尼诺。throw exsys通常不受欢迎,因为它在后面创建了一个新的堆栈,而throw不受欢迎。然而,这确实意味着你会收到这个警告——尽管这个异常不是直接使用的,你可能只需要捕获。投球,但还没试过
- 如果您不想使用这个异常,那么就没有必要去捕捉它。
- @尼诺真的,别这样。
- @Fabjan:提议的副本的公认答案使用catch (Exception exSys) { throw;},这正是OP想要避免的。所以这个问题是关于未使用的异常变量,而不是throw ex/throw。
- @查尔斯感谢你的建议。
- @Timschmelter或多或少,是的。在我看来,我既可以保留堆栈跟踪,也可以保持堆栈无警告。我甚至不能创建一个新的异常,因为这样的话,消息行就不会返回实际的错误。
- 你一直在问"新"问题,你已经有答案了。
- @马丁普利对不起,我不明白。没有新问题。这里只是根据作为答案的建议进行编辑。如果我尝试的方法都不起作用,我将在问题中添加这个细节。
- 如果要保留错误消息和堆栈,只需使用throw。你为什么一直尝试其他方法?
- 因为那样我就不能在那个接球区做任何事。我想创建一个日志或基于消息发送一封电子邮件,然后将异常传递给调用函数。如果我不声明变量,logText += ex.Message或类似的行将不起作用。实际上,我可以扔掉堆栈跟踪,只要vs不打扰我。
- 但您从未告诉我们您要在catch块中使用异常!查看我编辑的答案。
您不必将变量绑定到异常:
1 2 3 4 5 6 7 8 9
| try
{
...
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
} |
实际上,在您的情况下,当捕获任何异常时,您甚至不必命名异常类型:
1 2 3 4 5 6 7 8 9
| try
{
...
}
catch
{
bqBusinessQuery.RollBackTransaction();
throw;
} |
或者(如@zohar peled建议的那样)抛出一个新的异常,将捕获的异常用作内部异常。这样既可以保留堆栈,又可以为异常提供更多上下文。
1 2 3 4 5 6 7 8
| try
{
...
}
catch (Exception e )
{
throw new Exception ("Transaction failed", e );
} |
如果您确实想将异常用于某些处理(例如,记录它),但又想完整地重新执行它,请声明变量,但使用一个普通的throw:
1 2 3 4 5 6 7 8 9
| try
{
...
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
} |
- 另一种选择是:用原始异常抛出一个新的异常,因为它是内部异常:catch(Exception ex) { throw new Exception(ex)}。
- @佐哈佩莱谢谢。补充。
- 使用第三个选项,因为我希望保留内部异常消息,而不必处理警告。:)
- 好吧,你会得到所有这三个选项。
- 如果要抛出相同的异常,只需使用throw(前两个选项)。
- 这就是我最初的想法。但是,当e.message不在任何地方使用时,它就会发出警告。我想,我会用两种方法。当我必须使用异常时,我将声明变量,否则我将把它留空。扔吧,我会保持原样。:)
- 就是这样做的。如果需要变量,请声明它;如果不需要,请不要声明。
- 请编辑问题,以便清楚地表明您想要使用变量。那不是复制品。
1 2 3 4 5
| catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
} |
如果您不打算使用异常(例如,在某个地方传递消息),那么您就不需要将它拉出到变量中。你可以简单地捕捉,做定制的事情和投掷。
- 在某些情况下,我们会传递消息。例如,当查询验证失败时,throw new Exception("custom message");在应用程序中很常见。然后,它被转发到最外层的调用函数,该函数将更新UI以显示错误。
- 在这种情况下,应该使用ecx1(3),这样就不会丢失堆栈跟踪。
- 对于粉红的完美使用,你得到一个+1
- @凯尔米尔我能做埃多克斯1〔4〕。我不想添加任何新消息,只是保留异常首次发生时出现的原始消息。例如,execute query函数抛出异常,说primary key already exists,那么我只想回滚事务,让相同的异常消息通过。
- @Jitendragarg是的,这样做没什么错。我们经常捕获一般的异常,并用我们自己的自定义异常将它们包装起来,这样我们就可以进一步捕获并处理它们。例如,自定义数据库异常或其他。
- 伟大的。谢谢。那就行了。:)
- 等等,现在我有新问题了。` catch(system.exception ex)抛出新的system.exception(ex);不起作用。它给了我一个错误,说最佳重载方法有无效的参数。它确实需要一条错误消息。
- @你说得很对。对不起,太晚了,我累了。catch (Exception ex) { throw new Exception("Database Exception", ex); }或类似产品应工作良好:)
- 这导致了另一个问题。检查问题的编辑。
- 那么:catch (Exception ex) { throw new Exception(ex.Message, ex); }是一个值得思考的问题:如果你抛出了一个新的例外,而这个例外的信息与原来的完全相同——你为什么要这样做?
- 让我们在聊天中继续讨论。