Иллюстрированный самоучитель по Architecture .NET

Делегаты

Ключевое слово _delegate (делегат) используется для объявления класса-делегата, основанного на описании сигнатуры метода. Делегаты очень сходны с указателями на функции в обычном C++, с той лишь разницей, что делегат может указывать только на метод управляемого класса. Чаще всего в приложениях .NET Framework делегаты используются для реализации функций обратного вызова или обработки событий. Однако они могут найти применение во всех случаях, когда необходимо вызывать методы динамически.

В .NET Framework определены (как абстрактные классы) два типа делегатов – System::Delegate (Система::Делегат) и System::MulticastDelegate. Эти два типа делегатов используются как базовые классы для одноадресных (или делегатов единственного приведения – single-cast) и многоадресных (или групповых – multicast) делегатов соответственно. Одноадресный делегат связывает указатель на метод с методом одного управляемого объекта, тогда как многоадресный делегат связывает указатель на метод с одним или несколькими методами управляемого объекта. Вызов одноадресного делегата приводит к вызову только одного метода, а при вызове многоадресного делегата может выполняться неограниченное количество методов. В связи с тем, что многоадресный делегат можно использовать и для вызова одного метода, одноадресная форма делегата является излишней. Обычно в программах используются лишь многоадресные делегаты.

Встретив в программе ключевое слово _delegate (делегат) компилятор создает особый управляемый класс, производный от System::MulticastDelegate. Конструктор этого класса имеет два аргумента: указатель на экземпляр управляемого класса (который равен нулю, если делегат связывает статический метод), и сам метод, вызываемый с помощью делегата. Этот класс также содержит метод Invoke (Запустить), сигнатура которого совпадает с сигнатурой метода, вызываемого делегатом. Следующий пример демонстрирует использование делегатов:

//DelegateExample.срр
#using <mscorlib.dll>
using namespace System;
// использовать пространство имен Система;
// определить управляемые классы для использования
// в качестве делегатов
_delegate int SomeDelegate // делегат
(int i, int j);
_delegate // делегат
void SomeOtherDelegate (int i);
_gc class SomeClass
// класс сборщика мусора SomeClass содержит методы,
// вызываемые делегатами
{
public:
int SomeMethod(int i, int j)
{
Console::WriteLine(
"SomeMethod({0}, {!})", _box(i), _box(j));
return i+j; }
static int SomeStaticMethod(int i, int j) // статический
{
Console::WriteLine(
"SomeStaticMethod({0}, {!})", _box(i), _box(j));
return i+j; }
void SomeOtherMethod(int i) {
Console::WriteLine(
11 SomeOtherMethod ({0}) ", _box(i));
}
};
Void main ()
{
SomeDelegate *pscd; int sum; // сумма
// связать делегат с нестатическим методом
// требуется экземпляр
SomeClass SomeClass * psc = newSomeClass();
pscd = // создать экземпляр класса делегат sc new SomeDelegate(
psc, SSomeClass::SomeMethod); // нестатический
sum = pscd › Invoke(3, 4);
// вызвать метод через делегат
// сумма = pscd › вызвать (3, 4);
Console::WriteLine(sum); // сумма
// связать делегат со статическим методом, – нет нужды
// ни в каком экземпляре
pscd = // создать другой экземпляр класса делегата
sc new SomeDelegate((), SSomeClass::SomeStaticMethod);
// статический sum = pscd › Invoke(3, 4);
// вызвать метод через делегата
// сумма = pscd › вызвать (3, 4);
Console::WriteLine(sum); // сумма
// объединить два делегата
SomeClass * pscl = new SomeClass();
SomeClass * psc2 = new SomeClass(); SomeOtherDelegate *pmcdl = new SomeOtherDelegate(
psc1, &SomeClass::SomeOtherMethod); SomeOtherDelegate *pmcd2 = new SomeOtherDelegate(
psc2, SSomeClass::SomeOtherMethod); SomeOtherDelegate *pmcd =
static_cast<SomeOtherDelegate *>(Delegate:.Combine(
// Объединение делегатов pmcdl, pmcd2)); pmcd › Invoke(1); // Вызвать }
SomeMethod(3, 4)
7
SomeStaticMethod(3, 4)
7
SomeOtherMethod(I)
SomeOtherMethod(1)
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.