C# - 在不将其设置为变量的情况下重新抛出异常

时间:2011-05-02 15:08:26

标签: c# exception-handling

正如你们所有人都知道的那样,在c#中捕获并重新抛出异常这种方式是邪恶的,因为它会破坏堆栈跟踪:

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException ex)
{
    throw ex;
}

在不丢失堆栈跟踪的情况下重新抛出异常的正确方法是:

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException ex)
{
    throw;
}

唯一的问题是我收到了很多编译警告:“声明变量'ex'但从未使用过”。如果你有很多这些,可能会在垃圾中隐藏一个有用的警告。所以,这就是我所做的:

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException)
{
    throw;
}
catch(AnotherException ex)
{
    //handle it
}

这似乎有效,但我想知道重新抛出未设置为变量的异常是否有任何缺点。 .net如何威胁这个?

提前致谢

修改 我已经改变了我的代码,以便更清楚我想做什么,因为有些人误解了

6 个答案:

答案 0 :(得分:7)

没有任何缺点。您只是告诉编译器“我计划捕获此异常,但我不需要引用实际异常”,它不会影响抛出的方式或异常的工作方式。你的后一个例子是做你想做的事情的理想方式,但是如果你只是立即throw;在块中没有任何其他东西,那么为什么要抓住它?

答案 1 :(得分:6)

  

我想知道重新抛出未设置为变量的异常是否有任何缺点。

不,没有任何缺点。只有在您想在代码中引用异常时才需要变量,但由于您不需要使用throw语句,因此根本不需要变量。

在尝试消除“嘈杂”编译器警告时,您有正确的想法。他们倾向于埋葬您 想要修复的重要错误,并且获得干净的构建始终很重要。最好的解决方案是简单地重写代码以使用无参数catch子句。

但是,请注意,在我看到的82%的情况下,编写使用throw的代码是错误的。您通常不应该捕获您不知道如何处理的异常并且只是计划重新抛出。有些情况下即使使用throw也可以重置调用堆栈,导致丢失重要的调试信息。还有更好的替代方法可以记录捕获/重新抛出的异常。您可以在这些问题的答案中找到更多信息:

答案 2 :(得分:5)

如果你在DummyException块中没有使用catch做任何事情(你不能,因为你没有给它一个标识符),为什么不摆脱try/catch 1}}完全阻止?例如,只需这样做:

throw new DummyException();

虽然在那时,我可能会评估你在这里要完成的工作并重新考虑你的应用程序架构,以免不依赖于这种方式的异常传播。

答案 3 :(得分:1)

为什么要抓住你只是想重新投掷?无论如何,您可能想看一下之前的讨论。虽然所讨论的内容并不相同,但相关:

Throw VS rethrow : same result?

答案 4 :(得分:1)

实际上使用“throw;”抛出异常是.Net 最佳做法,因为它保留了异常堆栈跟踪。

使用“throw ex;”抛出异常被认为是最糟糕的做法,因为它会丢失原始堆栈跟踪,应该避免使用。

答案 5 :(得分:1)

为什么要抓住并重新抛出这样的东西?为什么人们总是必须假设他们知道每个案例?答:数据库交易。

如果您有更好的方法,请说出Proton博士,不要冒犯。请记住,有许多不同的数据库系统在使用,但大多数都支持事务控制(开始/提交/回滚)并具有C#接口。

伪代码(简化案例):

try
{
   db.beginTrans();

   db.doStuff();

   db.doOtherStuff();

   db.commitTrans();
}
catch
{
  db.rollbackTrans();
  throw;
}

现在,丢失doStuff()或doOtherStuff()失败的细节是非常烦人的,在这种情况下,我没有看到为什么C#会抛出行号信息。但它似乎。因此谷歌搜索和我随后的到来。如果我遗失了什么,请告诉我们。