c# - 什么会导致 throw 重置调用堆栈(我使用的是 "throw",而不是 "throw ex")

标签 c# .net exception exception-handling stack-trace

我一直认为“throw”和“throw ex”的区别was that throw alone wasn't resetting the stacktrace of the exception.

不幸的是,这不是我遇到的行为;这是一个重现我的问题的简单示例:

using System;
using System.Text;

namespace testthrow2
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                try
                {
                    throw new Exception("line 14");
                }
                catch (Exception)
                {
                    throw; // line 18
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());

            }
            Console.ReadLine();
        }
    }
}

我希望这段代码打印一个从第 14 行开始的调用堆栈;然而,调用堆栈从第 18 行开始。当然,这在示例中没什么大不了的,但在我的实际应用程序中,丢失初始错误信息是非常痛苦的。

我是否遗漏了一些明显的东西?有没有另一种方法来实现我想要的(即在不丢失堆栈信息的情况下重新抛出异常?)

我正在使用 .net 3.5

最佳答案

你应该阅读这篇文章:

简而言之,throw 通常 保留原始抛出异常的堆栈跟踪,但前提是异常未发生在当前堆栈帧(即方法)中.

有一种方法 PreserveStackTrace(在那篇博客文章中显示)可以像这样保留原始堆栈跟踪:

try
{

}
catch (Exception ex)
{
    PreserveStackTrace(ex);
    throw;
}

但我通常的解决方案是要么简单地不捕获并重新抛出这样的异常(除非绝对必要),要么总是使用 InnerException 属性抛出新的异常来传播原始异常:

try
{

}
catch (Exception ex)
{
     throw new Exception("Error doing foo", ex);
}

关于c# - 什么会导致 throw 重置调用堆栈(我使用的是 "throw",而不是 "throw ex"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5152265/

相关文章:

java - 为什么我的二进制到十进制转换程序读不到 0?

c# - 绕过聚合根

c# - 如何检查进程是否没有响应?

c# - 使用没有 foreach 的 LINQ 按类别划分产品列表

.net - 为什么在提供阿拉伯文本时 String.IndexOf 和 String.Contains 不一致?

wpf - 为什么 WPF 会吞下数据绑定(bind)异常?

c# - 很多 catch block ,但它们都具有相同的功能

c# - 我可以在 EF 中播种所需属性的数据吗?

c# - VS 2015 复制以输出项目引用的 GAC 引用,而不考虑复制本地设置

.net - Visual Studio 自动替换引用的程序集