了解之间的区别扔前 和 扔 ,为什么在这个例子中保留了原始的 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;
}
}
第二种情况产生与 相同的输出扔前 将?
在这两种情况下,都希望看到初始化 y 的行号。
最佳答案
我不确定此限制是否在 C# 语言、CLI 或 Microsoft 实现中,但您的第二个示例是显式调用 Exception.InternalPreserveStackTrace
的情况。是必需的,如以下帖子中所述。由于此方法是 internal
,一般要通过反射来调用。通过创建 Action<Exception>
几乎可以完全缓解与此相关的性能问题。电话,如本回答末尾所示。
引用:Rethrowing exceptions and preserving the full call stack trace
编辑:在重新检查 ECMA-335 Partition I §12.4.2(异常处理)和 Partition III §4.24(重新抛出)之后,我现在相信您看到的行为是 CLR(Microsoft 对 CLI 的实现)中的语义错误。对该行为的唯一特定引用是“A rethrow
不会更改对象中的堆栈跟踪。”在这里描述的情况下,重新抛出实际上改变了堆栈跟踪,使 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);
}
关于.net - 在 .NET 异常中保留原始堆栈跟踪/行号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1585082/