8

Suppose I have the following situation:

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        }

I run it and have the following output:

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

If I uncomment throw new Exception("Case 1"); the output is:

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

So my question is why in the first case I can see the full path including the Main function while I cannot see the same stuff in the second case. How can I display the more complete information if the production code is similar to the second case scenario.

Eugeniu Torica
  • 7,484
  • 12
  • 47
  • 62

3 Answers3

7

What you are seeing in your stack trace is the compiler's generated name for the anonymous function you are passing into WrapperMethod. There is no way to get a "prettier name" in this situation, short of not using anonymous functions.

However, when you know this, it shouldn't be hard to "mentally parse" the mangled Stack Trace. You can recognize the anonymous function by it's name which will be something like <Main>b__0(), and you can tell it was declared inside the Program class because that is where the compiler decided to generate the function.

You are not losing any stack information. If an exception is thrown inside WrapperFunction, that will be the topmost stack frame. If an exception is thrown inside a method that WrapperFunction calls, that (in this case, an anonymous) method will be on top in the stack.

driis
  • 161,458
  • 45
  • 265
  • 341
  • 4
    He's talking about losing the stack trace above the WrapperMethod. He wants to be able to trace all the way back to the method call in Main. – Pete M Mar 17 '11 at 17:37
  • 1
    @Pete M, he isn't losing any stack information, as far as I can tell. If an exception is thrown inside WrapperFunction, that will be the topmost stack frame. If an exception is thrown inside a method that WrapperFunction calls, that (in this case, an anonymous) method will be on top in the stack. – driis Mar 17 '11 at 17:40
  • @Pete: that is what the OP is asking but the supposed difference isn't there. – H H Mar 17 '11 at 17:41
  • @driis: I think that should have been your answer... ;o) +1 – Pete M Mar 17 '11 at 17:41
  • @driis - Why then in the first case there is Main function name shown but in the second place no. – Eugeniu Torica Mar 18 '11 at 09:14
  • 1
    @Jenea, because
    is a part of the compiler-generated name for your anonymous function.
    – driis Mar 18 '11 at 09:15
  • @driis - Is it ok for performance reasons (production code) to do new System.Diagnostics.StackTrace().ToString() which will show me the full stack trace path? – Eugeniu Torica Mar 18 '11 at 09:18
1

In the first case you are making another method call to the anonymous method that is defined inside the Main method. As the exception is thrown inside the anonymous method, it's included in the call stack.

If you throw the exception in the WrapperMethod method, then the anonymous method is never involved, so it won't show up in the call stack.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • No question about this fact but why I cannot see the entering point in the WrapperMethod, I mean the nr. of row where the function was called. – Eugeniu Torica Mar 18 '11 at 09:12
  • 2
    @Jenea: If you run the code in debug mode you will also get the point in the Main method in the stack trace. The reason that it doesn't show up in release mode is that you have so little code in the method that it's inlined. It actually doesn't exist in the compiled code. – Guffa Mar 18 '11 at 17:08
0

You are only seeing the stack trace as it is, nothing more nothing less.

The reason is Lambda expressions are jitted when they need to run and before that they are only stored in the form of data.

Aliostad
  • 80,612
  • 21
  • 160
  • 208