.net - 在 .NET 异常中保留原始堆栈跟踪/行号

标签 .net exception line-numbers

了解之间的区别扔前 ,为什么在这个例子中保留了原始的 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/

相关文章:

c# - 处理 Process.Start() 抛出的 Win32Exception

c# - async Task<bool> if 条件下的方法调用

python - 如何中断 Tornado 协程

emacs - 禁用行号但在程序模式和文本模式下允许它们

c# - 您如何计算出用户 MySite 的 ID

c# - Process.Start(url) 失败

c# - 多次指定固定名称 System.Data.SqlClient 的提供程序

C++ 赋值运算符异常安全

php - 在 PHP 中使用正则表达式时是否可以显示行号?

java - 从我的java程序控制java程序的执行