Подтвердить что ты не робот

В .NET, какова внутренняя реализация делегата?

Я понимаю, что объявление делегата выглядит примерно так:

public delegate int PerformCalculation(int x, int y);

Однако, должно быть больше. Цель делегата - предоставить указатель на метод и сделать это, чтобы инкапсулировать ссылку на метод в делегате.

Какая структура эта ссылка содержится внутри (внутри делегата)? Я также понимаю, что вы можете инкапсулировать ссылку на несколько методов в делегате. Означает ли это, что в делетете содержится массив?

Также, какие методы определены в делегате и т.д. Что действительно происходит, когда вы объявляете делегата с кратким:

public delegate int PerformCalculation(int x, int y);

?

РЕДАКТИРОВАТЬ: Некоторые пояснения. Когда вы объявляете делегата, компилятор автоматически создает закрытый класс, который наследует от System.MulticastDelegate для вас. Вы можете это увидеть, если посмотреть на свою сборку с помощью ildasm. Это аккуратно. В принципе, с одним утверждением вы получаете весь новый класс, сгенерированный для вас во время компиляции, и он обладает всеми необходимыми функциями.

4b9b3361

Ответ 1

Все делегаты наследуют тип System.Delegate, который содержит Target и Method. Точнее они наследуют от System.MultiCastDelegate, который наследуется от System.Delegate.

Ответ 2

Внутренне это ссылочный тип, очень похожий на класс. Транскрипция выглядит следующим образом:

public /* delegate */ class PerformCalculation : MulticastDelegate {
    public PerformCalculation(object target, IntPtr method) {}
    public virtual void Invoke(int x, int y) {}
    public virtual IAsyncResult BeginInvoke(int x, int y, AsyncCallback callback, object state) {}
    public virtual void EndInvoke(IAsyncResult result) {}
}

Я оставил реализации этих элементов пустыми, они фактически сопоставлены с кодом в CLR. Компилятор динамически генерирует сигнатуры метода, в зависимости от подписи объявления делегата. Обратите внимание на аргументы x и y. Компилятор JIT помогает получить вызов конструктора, используя синтаксис + = или - =, он знает адрес памяти целевого метода делегата. Компилятор автоматически сгенерировал значение целевого аргумента, в зависимости от того, был ли целевой метод статическим или нет. Два аргумента сопоставляются свойствам (Multicast) Delegate.Target и Method. Фактический экземпляр базового класса может быть либо делегатом, либо MulticastDelegate, в зависимости от того, сколько целей было подписано.

Здесь много секретного соуса.