Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Ответы по Технологии программирования / Многоадрессная передача

.docx
Скачиваний:
8
Добавлен:
21.05.2015
Размер:
7.57 Кб
Скачать

Одна из самых интересных возможностей делегата — поддержка многоадресатной передачи (multicasting). Многоадресатная передача — это способность создавать список вызовов (или цепочку вызовов) методов, которые должны автоматически вызываться при вызове делегата. Такую цепочку создать нетрудно.

Достаточно создать экземпляр делегата, а затем для добавления методов в эту цепочку использовать оператор "+=". Для удаления метода из цепочки используется оператор" - = " . (Можно также для добавления и удаления методов использовать в отдельностиоператоры "+", " - " и "=", но чаще применяются составные операторы "+=" и "-=".)

Делегат с многоадресатной передачей имеет одно ограничение: он должен возвращать тип void.

Рассмотрим следующий пример многоадресатной передачи. Это — переработанный вариант предыдущих примеров, в котором тип string для значений, возвращаемых методами обработки строк, заменен типом void, а для возврата модифицированных строк используется ref-параметр.

using System;

delegate void strMod(ref string str); // Объявляем делегат.

class StringOps {

// Метод заменяет пробелы дефисами,

static void replaceSpaces(ref string a) {

Console.WriteLine("Замена пробелов дефисами.");

a = a.Replace(‘‘,’–‘ ) ;

}

static void removeSpaces(ref string a) {// Метод удаляет пробелы.

string temp = "";

int i;

Console.WriteLine("Удаление пробелов.");

for(i=0; i < a.Length; i++)

if(a[i] != ‘ ’) temp += a[i];

a = temp;

}

// Метод реверсирует строку,

static void reverse(ref string a) {

string temp = "";

int i, j;

Console.WriteLine("Реверсирование строки.");

for(j=0, i=a.Length-l; i >= 0; i—, j++)

temp += a[i];

a = temp;

}

public static void Main() {

// Создаем экземпляры делегатов.

strMod strOp;

strMod replaceSp = new strMod(replaceSpaces);

strMod removeSp = new strMod(removeSpaces);

strMod reverseStr = new strMod(reverse);

string str = "Это простой тест.";

// Организация многоадресатной передачи.

strOp = replaceSp;

strOp += reverseStr;

// Вызов делегата с многоадресатной передачей.

strOp(ref str);

Console.WriteLine("Результирующая строка: " + str);

Console.WriteLine();

// Удаляем метод замены пробелов и

// добавляем метод их удаления.

strOp -= replaceSp;

strOp += removeSp;

str = "Это простой тест."; // Восстановление

// исходной строки.

// Вызов делегата с многоадресатной передачей.

strOp(ref str);

Console.WriteLine("Результирующая строка: " + str);

Console.WriteLine();

}}

Вот как выглядят результаты выполнения этой программы:

Замена пробелов дефисами.

Реверсирование строки.

Результирующая строка: .тсет-йотсорп-отЭ

Реверсирование строки.

Удаление пробелов.

Результирующая строка: .тсетйотсорпотЭ

В методе Main() создаются четыре экземпляра делегата. Первый, strOp, имеет null-значение. Три других ссылаются на методы модификации строк. Затем организуется делегат для многоадресатной передачи, который вызывает методы removeSpaces()и reverse(). Это достигается благодаря следующим строкам программы:

strOp= repiaceSp;

strOp += reverseStr;

Сначала делегату strOp присваивается ссылка replaceSp. Затем, с помощью оператора "+=", в цепочку вызовов добавляется ссылка reverseStr. При вызове делегата strOp в этом случае вызываются оба метода, заменяя пробелы дефисами и реверсируястроку.

Затем при выполнении строки программы

strOp -== replaceSp;

из цепочки вызовов удаляется ссылка replaceSp, а с помощью строкиstrOp += removeSp;в цепочку вызовов добавляется ссылка removeSp.

Затем делегат StrOp вызывается снова. На этот раз из исходной строки удаляютсяпробелы, после чего она реверсируется.

Цепочки вызовов, организованные с помощью делегата, — мощный механизм, который позволяет определять набор методов, выполняемых "единым блоком". Цепочки делегатов имеют особое значение для событий.

Все делегаты представляют собой классы, которые неявным образом выводятся из класса System.Delegate. Обычно его члены не используются напрямую. Все же в некоторых ситуациях его члены могут оказаться весьма полезными.

Делегаты используются по двум основным причинам.

Во-первых, делегаты обеспечивают поддержку функционирования событий.

Во-вторых, делегаты позволяют во время выполнения программы выполнить метод, который точно не известен в период компиляции. Эта возможность особенно полезна, когда нужно создать оболочку, к которой могли бы подключаться программныекомпоненты. Например, представьте графическую программу (наподобие стандартнойутилиты Windows Paint). Используя делегат, можно было бы разрешить пользователюподключать специальные цветные светофильтры или анализаторы изображений. Более того, пользователь мог бы создавать "свои" последовательности этих фильтровили анализаторов.