Использование делегатов

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

Делегаты применяются в основном для следующих целей:

□ получения возможности определять вызываемый метод не при компиляции,
а динамически во время выполнения программы;

□ обеспечения связи между объектами по типу «источник — наблюдатель»; □создания универсальных методов, в которые можно передавать другие методы;

□ поддержки механизма обратных вызовов.

Все эти варианты подробно обсуждаются далее. Рассмотрим сначала пример реа­лизации первой из этих целей. В листинге 10.1 объявляется делегат, с помощью которого один и тот же оператор используется для вызова двух разных методов

(С001 и Hack).

Листинг 10.1. Простейшее использование делегата

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System;

namespace ConsoleApplication1

{

delegate void Del(ref string s); // объявление делегата

class Class1

{

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

{

string temp = "";

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

{

if (s[i] == 'о' || s[i] == 'O')

temp += '0';

else

if (s[i] = '1')

temp += '1';

else

temp += s[i];

}

s = temp;

}

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

{

string temp = "";

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

if (i / 2 * 2 == i)

temp += char.ToUpper(s[i]);

else temp += s[i];

s = temp;

}

static void Main()

{

string s = "cool hackers";

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

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

{

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

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

d(ref s); // использование делегата для вызова методов

Console.WriteLine(s);

}

}

}

}

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

c00l hackers

С001 hAcKeRs

Использование делегата имеет тот же синтаксис, что и вызов метода. Если деле­гат хранит ссылки на несколько методов, они вызываются последовательно в том порядке, в котором были добавлены в делегат. Добавление метода в список выполняется либо с помощью метода Combine, унас­ледованного от класса System.Delegate, либо, что удобнее, с помощью перегружен­ной операции сложения. Вот как выглядит измененный метод Main из предыду­щего листинга, в котором одним вызовом делегата выполняется преобразование исходной строки сразу двумя методами:

static void Main()

{

string s = "cool hackers";

Del d = new Del(C001);

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

d(ref s);

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

}

При вызове последовательности методов с помощью делегата необходимо учи­тывать следующее:

□ сигнатура методов должна в точности соответствовать делегату;

□ методы могут быть как статическими, так и обычными методами класса;

□ каждому методу в списке передается один и тот же набор параметров;

□ если параметр передается по ссылке, изменения параметра в одном методе от­
разятся на его значении при вызове следующего метода;

□ если параметр передается с ключевым словом out или метод возвращает значение, результатом выполнения делегата является значение, сформированное
последним из методов списка (в связи с этим рекомендуется формировать списки только из делегатов, имеющих возвращаемое значение типа void);

□ если в процессе работы метода возникло исключение, не обработанное в том
же методе, последующие методы в списке не выполняются, а происходит по­
иск обработчиков в объемлющих делегат блоках;

□ попытка вызвать делегат, в списке которого нет ни одного метода, вызывает
генерацию исключения System.NullReferenceException.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: