对Exception.StackTrace的内容感到困惑

时间:2011-03-17 17:29:41

标签: c# clr

假设我有以下情况:

9     class Program
10        {
11            public static void WrapperMethod(Action func)
12            {
13                try
14                {
15                    //throw new Exception("Case 1");
16                    func.Invoke();
17                }
18                catch (Exception ex)
19                {
20                    Console.WriteLine(ex.StackTrace);
21                }
22            }
23    
24            static void Main(string[] args)
25            {
26                WrapperMethod(() => { throw new Exception("Case 2"); });
27            }
28        }

我运行它并输出以下内容:

at TestExceptions.Program.<Main>b__0() in c:\users\administrator\documents\visual studio 2010\Projects\TestExceptions\TestExceptions\Program.cs:line 26    
at TestExceptions.Program.WrapperMethod(Action func) in c:\users\administrator\documents\visual studio 2010\Projects\TestExceptions\TestExceptions\Program.cs:line 16

如果我取消注释抛出新的异常(“案例1”); 输出是:

at TestExceptions.Program.WrapperMethod(Action func) in c:\users\administrator\documents\visual studio 2010\Projects\TestExceptions\TestExceptions\Program.cs:line 15

所以我的问题是为什么在第一种情况下我可以看到包括Main函数的完整路径,而在第二种情况下我看不到相同的东西。 如果生产代码与第二种情况类似,如何显示更完整的信息。

3 个答案:

答案 0 :(得分:7)

您在堆栈跟踪中看到的是编译器为您传递给WrapperMethod的匿名函数生成的名称。在这种情况下,除了不使用匿名函数之外,没有办法获得“更漂亮的名字”。

然而,当你知道这一点时,不应该很难“精神上解析”受损的Stack Trace。您可以通过它的名称来识别匿名函数,它类似于<Main>b__0(),您可以告诉它在Program类中声明,因为这是编译器决定生成函数的地方。

您没有丢失任何堆栈信息。如果在WrapperFunction内抛出异常,那将是最顶层的堆栈帧。如果在WrapperFunction调用的方法中抛出异常,那么(在这种情况下,匿名)方法将位于堆栈的顶部。

答案 1 :(得分:1)

在第一种情况下,您要对Main方法中定义的匿名方法进行另一个方法调用。由于异常在匿名方法中抛出,它包含在调用堆栈中。

如果在WrapperMethod方法中抛出异常,则永远不会涉及匿名方法,因此它不会显示在调用堆栈中。

答案 2 :(得分:0)

您只是看到堆栈跟踪原样,仅此而已。

原因是Lambda表达式在需要运行时被jitted,之前它们只以数据的形式存储。