Ключевое слово _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->Bbi3BaTb (3, 4); Console::WriteLine(sum); // сумма
// связать делегат со статическим методом, - нет нужды
// ни в каком экземпляре
pscd = // создать другой экземпляр класса делегата sc new SomeDelegate(
О, SSomeClass::SomeStaticMethod); // статический sum = pscd->Invoke(3, 4); // вызвать метод через делегата // сумма = pscd->Bbi3B3Tb (3, 4); Console::WriteLine(sum); // сумма
// объединить два делегата SomeClass * pscl = new SomeClass(); SomeClass * psc2 = new SomeClass(); SomeOtherDelegate *pmcdl = new SomeOtherDelegate(
pscl, &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)