Прежде всего, я прочитал этот ответ, и нет, он только говорит о том, как это реализовано прямо сейчас < / em>, но не объясняет почему.

Вот пример программы (такой же, как здесь):

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();
    }
}

Который выводит следующий стек вызовов:

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

Обратите внимание на эти две строки:

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

Нижний (с invoke()) говорит, что есть пространство имен ConsoleApplication1 с классом Program в нем, который имеет член invoke(). Здесь слева направо соответствует внешнему внутреннему.

Верхний (с c__DisplayClass2) снова говорит, что есть пространство имен и класс ...

А затем есть c__DisplayClass2, что означает «волшебное имя, которое компилятор выбрал для хранения захваченных переменных», а затем есть <implMain>, как если бы это параметр для c__DisplayClass2. Таким образом, он читается так, как будто c__DisplayClass2 каким-то образом является частью Program, а implMain является частью c__DisplayClass2.

Теперь, как я вижу, логически это наоборот - есть метод implMain() и есть "волшебный класс" c__DisplayClass2, созданный специально для локальных переменных implMain(). Мне кажется, что верхняя строка должна выглядеть так:

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

(возможно, с некоторыми дополнительными символами для предотвращения возможных конфликтов), но я надеюсь, что моя идея ясна - так будет выглядеть, как будто c__DisplayClass2 создан специально для облегчения работы implMain().

Есть ли причина, по которой текущая реализация показывает имя метода (implMain) после имени класса захвата локальных переменных (c__DisplayClass2), а не наоборот?

0
sharptooth 8 Май 2013 в 14:08
Эта ссылка может быть интересной для чтения.
 – 
Sergey Kalinichenko
8 Май 2013 в 14:15

1 ответ

Лучший ответ

<implMain>b__0() - это просто название метода.

Осмотр в дизассемблере вам это покажет. < и > не подразумевают обобщения.

Включение implMain, вероятно, просто намекает, где был создан делегат.

3
leppie 8 Май 2013 в 14:16