了解之间的区别throw ex and throw,为什么在这个例子中保留了原来的StackTrace:
static void Main(string[] args)
{
try
{
LongFaultyMethod();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
static void LongFaultyMethod()
{
try
{
int x = 20;
SomethingThatThrowsException(x);
}
catch (Exception)
{
throw;
}
}
static void SomethingThatThrowsException(int x)
{
int y = x / (x - x);
}
但不是在这个:
static void Main(string[] args)
{
try
{
LongFaultyMethod();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
static void LongFaultyMethod()
{
try
{
int x = 20;
int y = x / (x - 20);
}
catch (Exception)
{
throw;
}
}
第二种情况产生的输出与throw ex would?
在这两种情况下,人们都希望看到 y 初始化的行号。
我不确定此限制是否存在于 C# 语言、CLI 或 Microsoft 实现中,但您的第二个示例是显式调用的情况Exception.InternalPreserveStackTrace
是需要的,如以下帖子中所述。由于该方法是internal
,一般必须通过反射来调用。通过创建一个Action<Exception>
用于通话,如本答案末尾所示。
参考:重新抛出异常并保留完整的调用堆栈跟踪 http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx
Edit:在重新检查 ECMA-335 Partition I §12.4.2(异常处理)和 Partition III §4.24(重新抛出)之后,我现在相信您所看到的行为是 CLR(Microsoft 的 CLI 实现)中的语义错误。对该行为的唯一具体提及是“Arethrow
不会改变对象中的堆栈跟踪。”在这里描述的情况下,重新抛出实际上改变了堆栈跟踪,使得PreserveStackTrace
破解已知 CLR 缺陷的解决方法。
static void LongFaultyMethod()
{
try
{
int x = 20;
int y = x / (x - 20);
}
catch (Exception ex)
{
PreserveStackTrace(ex); // <-- add this line
throw;
}
}
PreserveStackTrace
以下是对该博客条目的优化:
private static readonly Action<Exception> _internalPreserveStackTrace =
(Action<Exception>)Delegate.CreateDelegate(
typeof(Action<Exception>),
typeof(Exception).GetMethod(
"InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic));
public static void PreserveStackTrace(Exception e)
{
_internalPreserveStackTrace(e);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)