Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие КНЕУ.doc
Скачиваний:
24
Добавлен:
07.03.2016
Размер:
3.9 Mб
Скачать

10.1.2. Використання делегатів

Для того, щоб скористатися делегатом, необхідно створити його екземпляр і задати імена методів, на які він посилатиметься. При виклику екземпляра делегата викликаються всі задані в ньому методи.

  • Делегати застосовуються в основному для наступних цілей:

  • отримання можливості визначати метод, що викликається, не за допомогою компіляції, а динамічно під час виконання програми;

  • забезпечення зв'язку між об'єктами за типом “джерело - спостерігач”;

  • створення універсальних методів, в які можна передавати інші методи;

  • підтримка механізму зворотних викликів.

Розглянемо спочатку приклад реалізації першої з цих цілей. У лістингу 10.1 оголошується делегат, за допомогою якого один і той же оператор використовується для виклику двох різних методів (Сoo1 і Hack).

Лістинг 10.1. Просте використання делегата

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace examp65

{

delegate void Del ( ref string s ); // оголошення делегата

class Classl

{

public static void C001 ( ref string s ) // метод 1

{

Console.WriteLine( "викликаний метод Cool" );

s = s.Replace('l', '1').Replace('O', '0').Replace('o', '0');

}

public static void Hack ( ref string s ) // метод 2

{

char[] mas = s.ToCharArray();

s = "";

for (int i = 0; i < mas.Length; ++i)

s+= ((i & 1) == 0)? char.ToUpper(mas[i]):mas[i];

}

static void Main()

{

string s = "cOol hackers";

Del d; // екземпляр делегата

/*

d = new Del(C001); // ініціалізація методом 1

d += new Del(Hack);

*/

d = null;

for ( int i = 0; i < 2; i++)

{

if (i == 0) d = new Del(C001);

if (i == 1)d = new Del(Hack); // ініціалізація методом 2

d( ref s ); // використання делегата для виклику методів

Console.WriteLine(s);

}

}

}

}

Результат роботи програми:

cOOl hackers

COOl hAcKeRs

Використання делегата має той же синтаксис, що і виклик методу. Якщо делегат зберігає посилання на декілька методів, вони викликаються послідовно в тому порядку, в якому були додані в делегат.

Додавання методу в список виконується або за допомогою методу Combine, успадкованого від класу System.Delegate, або, що зручніше, за допомогою перевантаженої операції складання. От як виглядає змінений метод Main з попереднього лістингу, в якому одним викликом делегата виконується перетворення початкового рядка відразу двома методами:

static void Main()

{

string s = "cool hackers";

Del d = new Del ( C00l ) ;

d += new Del( Hack ); // додавання методу в делегат

d( ref s ) ;

Console.WriteLine( s ); // результат: C001 hAcKeRs

}

При виклику послідовності методів за допомогою делегата необхідно враховувати наступне:

  • сигнатура методів повинна в точності відповідати делегатові;

  • методи можуть бути як статичними, так і звичайними методами класу;

  • кожному методу в списку передається один і той же набір параметрів;

  • якщо параметр передається по посиланню, зміни параметра в одному методі відіб'ються на його значенні при виклику наступного методу;

  • якщо параметр передається з ключовим словом out або метод повертає значення, результатом виконання делегата є значення, сформоване останнім з методів списку (у зв'язку з цим рекомендується формувати списки тільки з делегатів, що мають повертаєме значення типу void);

  • якщо в процесі роботи методу виникло виключення, не оброблене в тому ж методі, подальші методи в списку не виконуються, а відбувається пошук обробників в охоплюючих делегат блоках;

  • спроба викликати делегат, в списку якого немає жодного методу, викликає генерацію виключення System.NullReferenceException.