Вопрос

Просматривая делегаты в C# и .NET в целом, я заметил несколько интересных фактов:

Создание делегата в C# создает класс, полученный из MulticastDelegate с конструктором:

.method public hidebysig specialname rtspecialname instance 
   void .ctor(object 'object', native int 'method') runtime managed { }

Это означает, что он ожидает экземпляра и указатель на метод. Тем не менее, синтаксис построения делегата в C# предполагает, что он имеет конструктор

new MyDelegate(int () target)

где я могу узнать int () как экземпляр функции (int *target() был бы указатель функции в C ++). Таким образом, очевидно, что компилятор C выбирает правильный метод из группы методов, определяемый именем функции, и создает делегат. Таким образом, первый вопрос был бы, откуда выбирает компилятор C# (или Visual Studio, точнее) выбирает эту подпись конструктора? Я не заметил никаких специальных атрибутов или чего -то, что будет отличаться. Это какая -то магия компилятора/VisualStudio? Если нет, это T (args) target Строительство действительно в C#? Мне не удалось что -то получить с этим, чтобы скомпилировать, например:

int () target = mymethod;

недействителен, так что делает что -то с MyMetod, например, призыв .ToString() на нем (ну, это имеет смысл, так как это технически метод группа, но я полагаю, что должно быть возможно явно выбрать метод путем кастинга, например, (int())MyFunction. Анкет Так все ли эта магия чисто компилятора? Глядя на строительство через отражатель, показывает еще один синтаксис:

Func cs $ 1 $ 0000 = новый фанк (null, (intptr) foo);

Это согласуется с подписью разобранного конструктора, но это не компилируется!

Последнее интересное примечание заключается в том, что классы Delegate а также MulticastDelegate иметь еще один набор конструкторов:

.method Family Hidebysig SpecialName RtsPecialName экземпляр void .ctor (Class System.Type Target, String 'Method') CIL управляется

Где происходит переход из экземпляра и указателя метода на тип и название метода строки? Можно ли объяснить runtime managed Ключевые слова в пользовательской подписи конструктора делегата, то есть, выполняет ли время выполнения свою работу здесь?

РЕДАКТИРОВАТЬ: Хорошо, я думаю, я должен переформулировать то, что я хотел сказать по этому вопросу. По сути, я предполагаю, что в магии компилятора / CLR COMPILER / CLR участвует в делегате, но также и некоторые Визуальная студия Магия, поскольку Intellisense выводит какой -то новый синтаксис, предлагая аргументы конструктора и даже скрывает один из них (например, отражатель не использует этот синтаксис и конструктор, в этом отношении).

Мне было интересно, является ли это утверждение правдой, и имеет ли синтаксис экземпляра функции некоторое более глубокое значение в C# или это просто какой -то постоянный формат, реализованный Magic Visual Studio Magic для Clarity (что имеет смысл, поскольку он выглядит как недействительный C#)? Короче говоря, если бы я внедрил Intellisense, я должен сделать магию для делегатов или я мог бы построить предложение с помощью какого -то умного механизма?

Окончательное редактирование: Итак, популярный консенсус в том, что это действительно против магии. Видя другие примеры (см. Комментарий Марка Граверэлла) такого поведения, убеждает меня, что это так.

Это было полезно?

Решение

Первый аргумент разрешен из ссылки на объект (или null для статических методов); Там нет магии.

В второй Аргумент, однако - это неуправляемый указатель (Native Int); Короче говоря, нет альтернативы непосредственный C# Синтаксис, который может использовать этот конструктор - он использует определенную инструкцию IL (ldftn) разрешить функцию из метаданных. Однако вы можете использовать Delegate.CreateDelegate создавать делегатов через отражение. Вы также можете использовать IL Emit (DynamicMethod и т.д.), но это не весело.

Другие советы

Сначала вы определяете делегат (именно так Visual Studio знает подпись целевого метода):

delegate void MyDelegate();

Затем вы строите такие случаи делегата, как это:

MyDelegate method = new MyDelegate({method name});

// If this was the method you wanted to invoke:
void MethodToInvoke()
{
    // do something
}

MyDelegate method = new MyDelegate(MethodToInvoke);

C# автоматически выбирает метод, соответствующий подписи делегата.

РЕДАКТИРОВАТЬ: Когда Intellisense Visual Studio показывает вам int () target Предложение, он показывает вам подпись методов C#, которые вы можете использовать. Компилятор C переводит представление C# на IL. Реализация IL будет выглядеть по -разному, потому что IL не является языком стиля C, а компилятор C# предоставляет синтаксический сахар, чтобы абстрагировать детали реализации.

Это просто предположение, так что не стреляйте в меня, если я ошибаюсь, но я думаю, что Intellisense получает подпись для целевого метода из Invoke Метод определяется на делегате. Отражатель ясно показывает, что Invoke Метод на System.Action<T> является:

[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);

Что такое же, как и предложение подписи, предлагаемое Intellisense. Магия - это Intellisense, обнаруживая тип делегата, смотрит на Invoke Метод и предлагает конструктор, который берет цель, которая соответствует ей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top