return temp;
}
// Обратить строку, public string Reverse(string s) { string temp = ""; int i, j;
Console.WriteLine("Обращение строки."); for(j=0, i=s.Length-1; i >= 0; i—, j++) temp += s[i];
return temp;
}
}
class DelegateTest { static void Main() {
StringOps so = new StringOpsO; // создать экземпляр
// объекта класса StringOps
// Инициализировать делегат.
StrMod strOp = so.ReplaceSpaces; string str;
// Вызвать методы с помощью делегатов, str = strOp("Это простой тест.");
Console.WriteLine("Результирующая строка: " + str);
Console.WriteLine();
strOp = so.RemoveSpaces;
str = strOp("Это простой тест.");
Console.WriteLine("Результирующая строка: " + str);
Console.WriteLine();
strOp = so.Reverse;
str = strOp("Это простой тест.");
Console.WriteLine("Результирующая строка: " + str);
}
}
Результат выполнения этого кода получается таким же, как и в предыдущем примере, но на этот раз делегат обращается к методам по ссылке на экземпляр объекта класса StringOps.
Групповая адресация
Одним из самых примечательных свойств делегата является поддержка групповой адресации. Попросту говоря, групповая адресация — это возможность создать список, или цепочку вызовов, для методов, которые вызываются автоматически при обращении к делегату. Создать такую цепочку нетрудно. Для этого достаточно получить экземпляр делегата, а затем добавить методы в цепочку с помощью оператора + или +=. Для удаления метода из цепочки служит оператор - или -=. Если делегат возвращает значение, то им становится значение, возвращаемое последним методом в списке вызовов. Поэтому делегат, в котором используется групповая адресация, обычно имеет возвращаемый тип 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 вызываются оба метода, заменяя пробелы дефисами и обращая строку, как и показывает приведенный выше результат.