假设我有以下情况:
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函数的完整路径,而在第二种情况下我看不到相同的东西。 如果生产代码与第二种情况类似,如何显示更完整的信息。
答案 0 :(得分:7)
您在堆栈跟踪中看到的是编译器为您传递给WrapperMethod的匿名函数生成的名称。在这种情况下,除了不使用匿名函数之外,没有办法获得“更漂亮的名字”。
然而,当你知道这一点时,不应该很难“精神上解析”受损的Stack Trace。您可以通过它的名称来识别匿名函数,它类似于<Main>b__0()
,您可以告诉它在Program
类中声明,因为这是编译器决定生成函数的地方。
您没有丢失任何堆栈信息。如果在WrapperFunction内抛出异常,那将是最顶层的堆栈帧。如果在WrapperFunction调用的方法中抛出异常,那么(在这种情况下,匿名)方法将位于堆栈的顶部。
答案 1 :(得分:1)
在第一种情况下,您要对Main
方法中定义的匿名方法进行另一个方法调用。由于异常在匿名方法中抛出,它包含在调用堆栈中。
如果在WrapperMethod
方法中抛出异常,则永远不会涉及匿名方法,因此它不会显示在调用堆栈中。
答案 2 :(得分:0)
您只是看到堆栈跟踪原样,仅此而已。
原因是Lambda表达式在需要运行时被jitted,之前它们只以数据的形式存储。