C# 4.0 полное руководство - 2011
Шрифт:
Console.WriteLine("Результирующая строка: " + str);
Console.WriteLine;
strOp = so.RemoveSpaces;
str = strOp("Это простой тест.");
Console.WriteLine("Результирующая строка: " + str);
Console.WriteLine;
strOp = so.Reverse;
str = strOp("Это простой тест.");
Console.WriteLine("Результирующая строка: " + str);
}
}
Результат
Групповая адресация
Одним из самых примечательных свойств делегата является поддержка групповой адресации. Попросту говоря, групповая адресация — это возможность создать список, или цепочку вызовов, для методов, которые вызываются автоматически при обращении к делегату. Создать такую цепочку нетрудно. Для этого достаточно получить экземпляр делегата, а затем добавить методы в цепочку с помощью оператора + или +=. Для удаления метода из цепочки служит оператор - или -=. Если делегат возвращает значение, то им становится значение, возвращаемое последним методом в списке вызовов. Поэтому делегат, в котором используется групповая адресация, обычно имеет возвращаемый тип void.
Ниже приведен пример групповой адресации. Это переработанный вариант предыдущих примеров, в котором тип значений, возвращаемых методами манипулирования строками, изменен на void, а для возврата измененной строки в вызывающую часть кода служит параметр типа ref. Благодаря этому методы оказываются более приспособленными для групповой адресации.
// Продемонстрировать групповую адресацию.
using System;
// Объявить тип делегата.
delegate void StrMod(ref string str);
class MultiCastDemo {
// Заменить пробелы дефисами.
static void ReplaceSpaces(ref string s) {
Console.WriteLine("Замена пробелов дефисами."); s = s.Replace(' ' , '-');
}
// Удалить пробелы.
static void RemoveSpaces(ref string s) { string temp = ""; int i;
Console.WriteLine("Удаление пробелов."); for(i=0; i < s.Length; i++) if(s[i] != ' ') temp += s[i];
s = temp;
}
// Обратить строку.
static void Reverse(ref string s) { string temp = ""; int i, j;
Console.WriteLine("Обращение строки."); for(j=0, i=s.Length-1; i >= 0; i—, j++) temp += s[i];
s = temp;
}
static void Main {
// Сконструировать делегаты.
StrMod strOp;
StrMod replaceSp = ReplaceSpaces;
StrMod removeSp = RemoveSpaces;
StrMod reverseStr = 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, является пустым, а три остальных ссылаются на конкретные методы видоизменения строки. Затем организуется групповая адресация для вызова методов RemoveSpaces () и Reverse . Это делается в приведенных ниже строках кода.
strOp = replaceSp; strOp += reverseStr
Сначала делегату strOp присваивается ссылка replaceSp, а затем с помощью оператора += добавляется ссылка reverseStr. При обращении к делегату strOp вызываются оба метода, заменяя пробелы дефисами и обращая строку, как и показывает приведенный выше результат.
Далее ссылка replaceSp удаляется из цепочки вызовов в следующей строке кода:
strOp -= replaceSp;
и добавляется ссылка removeSp в строке кода.
strOp += removeSp;
После этого вновь происходит обращение к делегату strOp. На этот раз обращается строка с удаленными пробелами.
Цепочки вызовов являются весьма эффективным механизмом, поскольку они позволяют определить ряд методов, выполняемых единым блоком. Благодаря этому улучшается структура некоторых видов кода. Кроме того, цепочки вызовов имеют особое значение для обработки событий, как станет ясно в дальнейшем.