为什么使用“throw ex;”会隐藏原始堆栈跟踪

7

3
你知道吗,如果想将原始异常及其堆栈跟踪一起重新抛出,可以使用 throw; 命令? - Adam
@codesparkle 是的,我知道 "throw" 的用法。但我只是想了解原因? - mkus
在这种情况下,你实际上正在问什么并不是很清楚。“为什么有一个带有新堆栈跟踪的命令”?因为设计者认为这样的东西足够有用,可以证明建造它的成本<=== 但这是每个这样的问题的答案,使其不特别启发。你实际想知道什么? - AakashM
不,这个问题目前在stackoverflow.com上并不是任何其他问题的精确副本。我知道throw;和throw ex;之间的最佳用法和区别,但我只想了解为什么c#架构师会以那种方式设计。 - mkus
2个回答

12
这实际上不是一个C#问题,而是一个CLI设计问题,与不同的IL指令throwrethrow有关。
基本上,throw ex;(对于任何ex,甚至包括原始异常)是一个IL throw,而throw;则是一个IL rethrow
如果你正在指定一个特定的要抛出的异常,那么这个异常逻辑上来说应该是源自这里,现在,这个方法。如果不是这种情况,那么:
throw;

不要使用throw ex;,而应该包装异常到另一个异常中,这样可以保留原始异常并且显示新异常的来源:

throw new SomeException(ex);

如果情况允许,调用者可以通过 ex.InnerException 获取原始的堆栈跟踪。


"throw ex是一种犯罪行为"这句话很引人注目,但它并没有描述为什么会是犯罪。你对IL中的throwrethrow的解释帮助了我理解。谢谢。 - twip

2
当您捕获异常时,它的“诞生地”在其他地方,异常会沿着堆栈跟踪一直到抛出异常的位置。可以将其视为throw初始化了Exception类实例的堆栈跟踪。因此,throw ex;使用当前堆栈初始化了ex的堆栈跟踪。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接