【问题标题】:StackTrace behavior in case of rethrow exception c#重新抛出异常时的 StackTrace 行为 c#
【发布时间】:2021-08-03 18:51:03
【问题描述】:

正如我现在已经知道的那样,为了保留原来的 stackTrace,我们应该避免使用 throw 捕获异常,相反,我们应该只使用 throw clause 实际上 @987654325 @异常。

问题是在几天前的一次采访中,我得到了一个代码来预测最终结果的stacktrace

class Program
{
    static void Main(string[] args)
    {
        try
        {
            ReThrowException(); // line 17
        }
        catch (Exception x)
        {
            Console.WriteLine("Exception:");
            Console.WriteLine(x.StackTrace); //line 22
        }
    }

    private static void ReThrowException()
    {
        try
        {
            DivByZero(); 
        }
        catch
        {
            throw; //line 34
        }
    }

    private static void DivByZero()
    {
        int x = 0;
        int y = 1 / x; //line 41
    }
}

异常发生在 line 41 和第 34 行,它只是 rethrow 异常,保留原来的 stackTrace

我的回答是:

它实际上应该指向line 41where 异常 第一次发生且无处 stackTrace 被覆盖 代码。

但真正的答案如下:

Exception:
   at TestConsole.Program.DivByZero() in C:...\Projects\TestConsole\TestConsole\Program.cs:line 41
   at TestConsole.Program.ReThrowException() in C:...\Projects\TestConsole\TestConsole\Program.cs:line 34
   at TestConsole.Program.Main(String[] args) in C:...\Projects\TestConsole\TestConsole\Program.cs:line 17

现在我想到了两个问题:

1.为什么stackTrace 为行17,34 添加源?
2.我应该在代码中做些什么来让stackTrace指向line 41并删除其他来源?

【问题讨论】:

  • 它没有显示“其他来源”。这是一个 stack 跟踪:它显示了引发异常时的调用堆栈。可能有很多地方调用了DivByZero,堆栈跟踪显示了确切调用它的方法,以及调用那个方法的方法,等等,一直到应用程序的入口点(或线程处理程序,如果它是在后台线程等)。上面写着“Main 在第 17 行调用了 ReThrowException;ReThrowException 在第 34 行调用了 DivByZero(除了它到达了 'throw' 点,而不是原始方法调用);DivByZero 在第 41 行遇到了问题”。
  • 你是对的,但是当它指向第 34 行时,似乎我使用的是 throw ex 而不是 throw 子句。
  • 没有。如果您使用了throw ex;,您将丢失指向DivByZero 中第41 行的堆栈跟踪部分。 throw ex; 会彻底清除目前为止记录的堆栈跟踪,重新开始
  • 是的,在这种情况下我失去了原件,但它表现得就像我在第 34 行抛出异常。
  • 不,不是——你读错了。查看第一个条目以查看引发异常的位置。其余条目显示您的异常“命中”的代码点,直到它最终被捕获并打印。堆栈跟踪没有显示代码中引发异常的所有点:它显示了异常在您的代码中冒泡时通过的所有点。

标签: c# try-catch stack-trace throw


【解决方案1】:

1.为什么 stackTrace 会为第 17,34 行添加源代码?

这不是其他sources,而是stack 跟踪显示导致异常的跟踪。 正如名称StackTrace 所暗示的那样,它不是一个点,同样它是一个path

2.在代码中我应该怎么做才能让stackTrace指向第41行并删除其他来源?

你不能,因为你的问题来自对 stackTrace 存在的误解。

【讨论】:

    【解决方案2】:

    “我应该在代码中怎么做才能让 stackTrace 指向第 41 行并删除其他来源?”

    不要在第 34 行抓住它?

    您应该只捕获您知道如何处理的异常。如果你曾经 catch()catch(Exception) ,那么你可能错了(除非它用于记录并且你重新抛出)。

    请记住,例外是“昂贵的”。你应该尽量避免它们。除以零是每个都停止,如果您的代码有一个零除数是“正常的”,那么这不是例外,应该用if 捕获。

    【讨论】:

    • 在这种情况下,堆栈跟踪仍然会有一个ReThrowException 的条目,只是它将显示该条目的第 30 行而不是第 34 行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    相关资源
    最近更新 更多