Что означает имя "DisplayClass" при вызове лямбды?

Согласно этому ответу, когда код использует локальные переменные внутри лямбда-методов, компилятор сгенерирует дополнительные классы, которые могут иметь имена, такие как c__DisplayClass1, Например, следующий (совершенно бесполезный) код:

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

Обратите внимание, что есть c__DisplayClass2 там есть имя класса, сгенерированного компилятором для хранения переменной цикла.

Согласно этому ответу c__DisplayClass "средства"

c -> класс закрытия анонимного метода ("DisplayClass")

Хорошо, но что здесь означает "DisplayClass"?

Что этот сгенерированный класс "отображает"? Другими словами, почему это не "MagicClass", "GeneratedClass" или какое-либо другое имя?

3 ответа

Решение

От ответа на связанный вопрос Эрика Липперта:

Причина, по которой класс замыкания называется "DisplayClass", несколько неудачна: этот жаргон используется командой отладчика для описания класса, который имеет особые поведения при отображении в отладчике. Очевидно, что мы не хотим отображать "x" как поле класса с невозможным именем, когда вы отлаживаете код; скорее, вы хотите, чтобы он выглядел как любая другая локальная переменная. В отладчике есть специальное оборудование для этого класса отображения. Вероятно, вместо этого он должен был называться "ClosureClass", чтобы было легче читать разборки.

Вы можете получить некоторую информацию из источника компилятора C#, который доступен из дистрибутива SSCLI20, подкаталога csharp/sccomp. Поиск кода "display" дает большинство совпадений в файле исходного кода fncbind.cpp. Вы увидите, что это используется в символах кода, а также в комментариях.

Комментарии убедительно свидетельствуют о том, что этот термин использовался внутри команды, возможно, еще во время совещаний по проектированию. Это устаревший код.NET 2.0, пока не было много переписывания кода. Просто итераторы и анонимные методы, реализованные очень похожими способами. Термин "класс отображения" смещен от "пользовательского класса" в комментариях, явный намек на то, что они использовали этот термин для обозначения автоматически сгенерированных классов. Нет четкого намека на то, почему "display" предпочтительнее, я подозреваю, что это может быть связано с тем, что эти классы видны в метаданных сборки.

Основанный на Reflector, DisplayClass можно перевести как CompilerGeneratedClass

[CompilerGenerated]
private sealed class <>c__DisplayClass16b
{
// Fields
public MainForm <>4__this;
public object sender;

// Methods
public void <cmdADSInit_Click>b__16a()
  {
    ADS.Initialize();
    this.<>4__this._Sender = this.sender;
    this.<>4__this.SelectedObject = ADS.Instance;
  }
}
Другие вопросы по тегам