Как методы типа делегата генерируются внутри? - PullRequest
1 голос
/ 22 августа 2011

Я знаю, что тип делегата наследуется от MulticastDelegate, который, в свою очередь, наследуется от класса Delegate.

Также, когда мы создаем экземпляр делегата, он создает три метода (Invoke, BeginInvoke, EndInvoke, кроме конструктора) с одинаковой подписью делегата.

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

Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 22 августа 2011

Если вы посмотрите на IL-тип делегата в Reflector или ILSpy, вы увидите, что он выглядит примерно так:

.class public sealed System.Action extends System.MulticastDelegate
{
    .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed {}

    .method public hidebysig newslot virtual instance void Invoke() runtime managed {}

    .method public hidebysig newslot virtual instance class System.IAsyncResult BeginInvoke(class System.AsyncCallback callback, object 'object') runtime managed {}

    .method public hidebysig newslot virtual instance void EndInvoke(class System.IAsyncResult result) runtime managed {}
}

, то есть методы конструктора (.ctor), Invoke и BeginInvoke/EndInvoke. Вы также заметите, что эти методы не имеют реализации (тела методов пусты) и помечены runtime.

Ключевое слово runtime указывает CLR, что этот метод нуждается в реализации, предоставляемой самим CLR. То есть реализация делегата является полностью магической внутри самого CLR. Когда тип делегата загружен, CLR замечает, что он получен из System.Delegate, замечает флаг runtime и создает реализации этих методов внутри CLR для этого конкретного типа делегата.

То, как эти реализации на самом деле выглядят, полностью зависит от CLR, на котором вы его запускаете (будь то платформа .NET, Mono или что-то еще), но, скорее всего, будет непосредственно в нативном коде.

Когда компилятор компилирует тип делегата, он просто создает эти заглушки методов для соответствия этому шаблону, ожидаемому CLR, и оставляет его при этом. Как на самом деле работает делегат, зависит от времени выполнения.

2 голосов
/ 22 августа 2011

Допустим, например, у нас есть такой делегат:

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

Как компилятор знает, как определить Invoke (), BeginInvoke () и Методы EndInvoke ()?

Это сгенерированный класс компилятором:

sealed class BinaryOp : System.MulticastDelegate
{
public BinaryOp(object target, uint functionAddress);
public int Invoke(int x, int y);
public IAsyncResult BeginInvoke(int x, int y,AsyncCallback cb, object state);
public int EndInvoke(IAsyncResult result);
}

Во-первых, обратите внимание, что параметры и возвращаемое значение точно определены для метода Invoke () соответствует определению делегата BinaryOp.

Начальные параметры для членов BeginInvoke () (в нашем случае два целых числа) также основаны на делегате BinaryOp;
однако BeginInvoke () всегда будет предоставлять два последних параметра (типа AsyncCallback и object), которые используются для облегчения вызова асинхронных методов.

Наконец, возвращаемое значение EndInvoke () идентично оригинальному объявление делегата и всегда будет принимать в качестве единственного параметра объект, реализующий Интерфейс IAsyncResult.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...