正如你们所有人都知道的那样,在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如何威胁这个?
提前致谢
修改 我已经改变了我的代码,以便更清楚我想做什么,因为有些人误解了
答案 0 :(得分:7)
没有任何缺点。您只是告诉编译器“我计划捕获此异常,但我不需要引用实际异常”,它不会影响抛出的方式或异常的工作方式。你的后一个例子是做你想做的事情的理想方式,但是如果你只是立即throw;
在块中没有任何其他东西,那么为什么要抓住它?
答案 1 :(得分:6)
我想知道重新抛出未设置为变量的异常是否有任何缺点。
不,没有任何缺点。只有在您想在代码中引用异常时才需要变量,但由于您不需要使用throw
语句,因此根本不需要变量。
在尝试消除“嘈杂”编译器警告时,您有正确的想法。他们倾向于埋葬您 想要修复的重要错误,并且获得干净的构建始终很重要。最好的解决方案是简单地重写代码以使用无参数catch
子句。
但是,请注意,在我看到的82%的情况下,编写使用throw
的代码是错误的。您通常不应该捕获您不知道如何处理的异常并且只是计划重新抛出。有些情况下即使使用throw
也可以重置调用堆栈,导致丢失重要的调试信息。还有更好的替代方法可以记录捕获/重新抛出的异常。您可以在这些问题的答案中找到更多信息:
答案 2 :(得分:5)
如果你在DummyException
块中没有使用catch
做任何事情(你不能,因为你没有给它一个标识符),为什么不摆脱try/catch
1}}完全阻止?例如,只需这样做:
throw new DummyException();
虽然在那时,我可能会评估你在这里要完成的工作并重新考虑你的应用程序架构,以免不依赖于这种方式的异常传播。
答案 3 :(得分:1)
为什么要抓住你只是想重新投掷?无论如何,您可能想看一下之前的讨论。虽然所讨论的内容并不相同,但相关:
答案 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#会抛出行号信息。但它似乎。因此谷歌搜索和我随后的到来。如果我遗失了什么,请告诉我们。