Слайд 2Одиночний делегат
Посилання на функції
Зворотній виклик
При роботі с Win API
С, С++
Виклик
глобальних функцій
Виклик статичних функцій
Виклик функцій об’єкта. Необхідне посилання на об’єкт.
Слайд 3Делегат
Делегат – об'єкт, безпечний по відношенню до типів, що вказують
на метод
Містить:
посилання на об'єкт
посилання на метод
жорстко визначає типи і
кількість параметрів методу
жорстко визначає тип значення, що повертається
Може вказувати на статичний метод чи метод екземпляра
Якщо посилання на обєкт дорівнює null, то це значить, що метод, якмй викликається є статичним
Забезпечує зворотній виклик
Виклик делегата синтаксично такий же як виклик звичайної функції
Слайд 4Робота з делегатами
Об'явити (описати) делегат
Описати тип делегата, використовуючи спеціальний синтаксис
(описати клас)
Створити екземпляр делегата
Об'явлення звичайної змінної типу
Виклик конструктора
Передача конструктору посилання
на метод екземпляра або статичний метод
Викликати делегат
Слайд 5Об'явлення типу делегата
Синтаксис
[attributes] [modifiers] delegate return-type type-name(args-list);
схоже на визначення
абстрактного метода, але це визначення типу
жорстко задає сигнатуру метода, що
викликається
Приклади
public delegate double Function2d(double x, double y);
public delegate Complex ComplexFunction(Complex z);
public delegate void EventHandler(object o, EventArgs e);
Слайд 6Приклад:
public delegate double ProcessResults(double x, double y);
За лаштунками (створюється клас
- нащадок від MulticastDelegate)
public sealed class ProcessResults : System.MulticastDelegate
{
public
ProcessResults (object target, uint funcAdress); // для розуміння
public object Target { get; }
public MethodInfo Method { get; }
public double Invoke (double x, double y); // Сигнатура співпадає
…..
}
Виклик делегата синтаксично такий же як виклик звичайної функції, але реально буде викликатися метод Invoke
Створюються ще методи BeginInvoke() і EndInvoke() для асинхронного виклику метода
Самостійно не можна створити клас - нащадок від MulticastDelegate або від Delegate. Тільки через синтаксис delegate
Слайд 7Створення (екземпляра) делегата
При створенні потрібно зв'язати з методом, що викликається
(передати в конструктор)
Для метода екземпляра
ProcessResults del = new ProcessResults(objectName.Function);
Для статичного
метода
ProcessResults del = new ProcessResults(typeName.Function);
Скорочений запис
ProcessResults del = objectName.Function;
ProcessResults del = typeName.Function;
Сигнатура метода і делегата повинна співпадати
Слайд 8Виклик делегата
Як і виклик звичайної функції, де як функція, що
викликається, вказується екземпляр делегата
double d = del(x, y);
double d =
del(4+12, 37);
Викликати метод Invoke не рекомендується, але і не забороняється. В деяких випадках це необхідно.
double d = del.Invoke(4+12, 37);
Слайд 9Делегати як параметри функції
Делегати можна використовувати для передачі функцій як
параметрів
public delegate double RealFunc (double x);
public double Integrate (double a,
double b, int n, RealFunc f)
{
double dx = (b – a) / n, res = 0.0;
for(int j = 0; j < n; j++)
res += f (a + j * dx) * dx;
return res;
} // end of Integrate()
double s = Integrate(0, 1, 1000, Math.Sin);
Слайд 10Ланцюжок делегатів
Дозволяє, викликавши один делегат, послідовно викликати декілька методів (з
однаковою сигнатурою)
public abstract class MulticastDelegate : Delegate
{
public sealed override Delegate[]
GetInvocationList(); // повертає список делегатів
private IntPtr _invocationCount;
private object _invocationList;
…
}
MulticastDelegate може зберігати посилання не на одну функцію, а на декілька
Під час виклику делегата функції можуть виконуватися в довільному порядку
Якщо функції повертають значення, то тільки останнє значення можна буде використовувати
У випадку виникнення необробленої виключної ситуації, переривається весь ланцюжок
Слайд 11Клас Delegate
public abstract class Delegate : ICloneable{
public static Delegate Combine
(params Delegate[] delegates);
public static Delegate Combine (Delegate delegate1, Delegate delegate2);
public
static Delegate Remove (Delegate source, Delegate value);
public static Delegate RemoveAll (Delegate source, Delegate value);
public virtual Delegate[] GetInvocationList();
…
}
Класи Delegate і MulticastDelegate незмінювані, тому всі методи комбінації делегатів статичні і повертають новий екземпляр делегата
Combine() – об'єднує делегати або ланцюжки делегатів у новий ланцюжок делегатів
Remove() – знищує вказаний делегат з ланцюжка (перший, що зустрівся з кінця)
RemoveAll() – знищує усі копії вказаного делегата із ланцюжка
GetInvocationList() – повертає ланцюжок делегатів у вигляді масиву одиночних делегатів
Слайд 12Скорочення запису створення ланцюжка делегатів
Використання операції додавання і віднімання +,
-.
Використання += і -=
Приклади:
ProcessResult delegate1 = new …., delegate2 =
new ….
ProcessResult chain = delegate1 + delegate2;
chain += delegate3;
ProcessResult chain = (ProcessResult)Delegate.Combine(delegate1, delegate2);
Слайд 13Ланцюжок делегатів
Виклик ланцюжка делегатів такий же (послідовно викликаються всі методи
в цьому ланцюжку)
double d = chain(5, 10);
Ітерація по ланцюжку делегатів
Delegate[]
delegates = chain.GetIvocationList();
ProcessResult pr = (ProcessResult) delegates[0];
double result = pr(5, 6);
foreach (ProcessResult del in chain.GetInvocationList())
{
Console.WriteLine(del(x,y));
}