Делегаты в.NET: как они создаются?

При осмотре делегатов в 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, чтобы быть точным) выбирают эту подпись конструктора от? Я не заметил специальных атрибутов или чего-то, что сделает различие. Действительно ли этот своего рода compiler/visualstudio является волшебным? В противном случае T (args) target конструкция, допустимая в C#? Мне не удалось заставить что-либо с ним компилировать, например:

интервал () предназначается = MyMethod;

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

Func $1 CS$0000 = новый Func (пустой указатель, (IntPtr) Foo);

Это согласовывается с демонтированной подписью конструктора, все же это не компилирует!

Одно заключительное интересное примечание то, что классы Delegate и MulticastDelegate имейте еще одни группы конструкторов:

Семейство .method hidebysig specialname rtspecialname экземпляр освобождает .ctor (система классов. Введите цель, представьте 'метод' в виде строки), cil управляемый

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

Править: хорошо, таким образом, я предполагаю, что должен повторно сформулировать то, что я хотел сказать этим вопросом. В основном я предполагаю, что нет только компилятора C# / волшебство CLR, вовлеченное в конструкцию делегата, но также и некоторое волшебство Visual Studio, начиная с зеркальных отражений Intellisense некоторый новый синтаксис при предложении аргументов конструктора, и даже скрывает одного из них (например, Отражатель не использует этот синтаксис и construtor, в этом отношении).

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

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: таким образом популярное согласие состоит в том, что это - действительно волшебство VS. Наблюдение других примеров (см. комментарий Marc Gravell) такого поведения VS убеждает меня, что это имеет место.

14
задан Saulius Valatka 14 March 2010 в 22:12
поделиться

3 ответа

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

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

12
ответ дан 1 December 2019 в 14:43
поделиться

Сначала вы определяете делегат (так 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# автоматически выбирает метод, соответствующий сигнатуре делегата.

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

0
ответ дан 1 December 2019 в 14:43
поделиться

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

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

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

0
ответ дан 1 December 2019 в 14:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: