0

First of all, I've read this answer and no, it only says how it is implemented right now, but doesn't explain why.

Here's a sample program (same as here):

class Program
{
    static void Main()
    {
        try {
            implMain();
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }

    static void implMain()
    {
        for (int i = 0; i < 10; i++) {
            invoke(() => {
                Console.WriteLine(i);
                throw new InvalidOperationException();
            });
        }
    }
    static void invoke(Action what)
    {
        what();
    }
}

which outputs the following call stack:

System.InvalidOperationException
at ConsoleApplication1.Program.<>c__DisplayClass2.<implMain>b__0()
at ConsoleApplication1.Program.invoke(Action what)
at ConsoleApplication1.Program.implMain()
at ConsoleApplication1.Program.Main()

Note these two lines:

at ConsoleApplication1.Program.<>c__DisplayClass2.<implMain>b__0()
at ConsoleApplication1.Program.invoke(Action what)

The lower one (with invoke()) says that there's namespace ConsoleApplication1 with class Program in it that has member invoke(). Here left-to-right corresponds to outer-to-inner.

The upper one (with c__DisplayClass2) says again there's a namespace and a class...

and then there's c__DisplayClass2 which means "a magic name the compiler chosen for storing captured variables" and then there's <implMain> as if it is a parameter to c__DisplayClass2. So it reads as if c__DisplayClass2 somehow is part of Program and implMain is part of c__DisplayClass2.

Now as I see it it's logically the opposite - there's implMain() method and there's "magic class" c__DisplayClass2 crafted specifically for implMain() local variables. So to me it looks like the upper line should look like this:

at ConsoleApplication1.Program.implMain.c__DisplayClass2.b__0()

(maybe with some extra symbols to prevent possible conflicts) but I hope my idea is clear - this way it would look like c__DisplayClass2 is crafted specifically to facilitate implMain() functioning.

Is there any reason why the current implementation shows the method name (implMain) after the local variables capture class name (c__DisplayClass2) and not vice versa?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979

1 Answers1

3

<implMain>b__0() is just the name of the method.

Inspection in a disassembler will show you this. The < and > does not imply generics.

The inclusion of implMain probably just hints where the delegate was created.

leppie
  • 115,091
  • 17
  • 196
  • 297