Цель работы: Освоить применение делегатов и событий. Многоадресная передача. Одна из самых интересных возможностей делегата — поддержка многоадресной передачи (multicasting). Выражаясь простым языком, многоадресная передача — это способность создавать список вызовов (или цепочку вызовов) методов, которые должны автоматически вызываться при вызове делегата. Такую цепочку создать нетрудно. Достаточно создать экземпляр делегата, а затем для добавления методов в эту цепочку использовать оператор "+=". Для удаления метода из цепочки используется оператор "-= ". Можно также для добавления и удаления методов использовать в отдельности операторы "+", " - " и "=", но чаще применяются составные операторы "+=" и "-=". Методы, помещённые в такую цепочку, будут вызваться по очереди, согласно их добавлению. Ограничение: Делегат с многоадресной передачей имеет одно ограничение: он должен возвращать тип void. Рассмотрим пример оконного приложения. privateclasstаlker { constint ff = 7; //метод, выводящий на экран колличество делегатов в цепочке. publicstaticvoid say(String say_t) { MessageBox.Show("in queue=" + say_t); } } publicdelegatevoiddsay(String dstring); // обьявляем делегат dsay dsayo; // производим первичное определение делегата, без инициализиции. // кнопка, добавляющая метод в цепочку делегат. privatevoid button1_Click(object sender, EventArgs e) { dsayo += newdsay(talker.say); // сам процессс добавления dsayo(Convert.ToString(dsayo.GetInvocationList().Count())); // вызов делегата, то есть всей цепочки методов. } //кнопка, удаляющая метод из делегата. privatevoid button2_Click(object sender, EventArgs e) { dsayo -= newdsay(talker.say); dsayo(Convert.ToString(dsayo.GetInvocationList().Count())); } События. На основе делегатов построено еще одно важное средство С#: событие (event). Событие — это автоматическое уведомление о выполнении некоторого действия. События работают следующим образом. Объект, которому необходима информация о некотором событии, регистрирует обработчик для этого события. Когда ожидаемое событие происходит, вызываются все зарегистрированные обработчики. А теперь внимание: обработчики событий представляются делегатами. События — это члены класса, которые объявляются с использованием ключевого слова event. Наиболее распространенная форма объявления события имеет следующий вид: event событийный делегат объект; Здесь элемент событийный делегат означает имя делегата, используемого для поддержки объявляемого события, а элемент объект — это имя создаваемого событийного объекта. Рассмотрим пример: using System; // Объявляем делегат для события, delegate void MyEventHandler(); // Объявляем класс события, class MyEvent { public event MyEventHandler SomeEvent; // Этот метод вызывается для генерирования события, public void OnSomeEvent() { if(SomeEvent != null) SomeEvent(); } } class EventDemo { // Обработчик события, static void handler() { Console.WriteLine("Произошло событие."); } public static void Main() { MyEvent evt = new MyEvent(); // Добавляем метод handler() в список события, evt.SomeEvent += new MyEventHandler(handler); // Генерируем событие, evt.OnSomeEvent(); } } // конец При выполнении программа отображает следующие результаты: Произошло событие. Все события активизируются посредством делегата. Следовательно, событийный делегат определяет сигнатуру для события. В данном случае параметры отсутствуют, однако событийные параметры разрешены. Поскольку события обычно предназначены для многоадресной передачи, они должны возвращать значение типа void. Обратите внимание на то, что обработчик события вызывается только в том случае, если делегат SomeEvent не равен null-значению. Поскольку другие части программы, чтобы получить уведомлении о событии, должны зарегистрироваться, можно сделать так, чтобы метод OnSomeEvent () был вызван до регистрации любого обработчика события. Чтобы предотвратить вызов null-объекта. Внутри класса EventDemo создается обработчик события handler(). В этом примере обработчик события просто отображает сообщение, но ясно, что другие обработчики могли бы выполнять более полезные действия. Задание 1: Реализовать оконное приложение с кнопкой "talk" и полем ввода текста. Реализовать класс Talker, содержащий метод Say, принимающий строку из поля ввода и производящий вывод ее на экран. Добавить в класс формы поле-делегат. При нажатии на кнопку "talk" на форме должен производиться вызов метода Talkrer.Say при помощи делегата и передача ему строки, введенной в поле ввода. Добавить в приложение класс Writer, содержащий метод Write, принимающий строку и производящий запись этой строки в файл "log.txt". Добавить на форму кнопку "write", нажатие на которую приводило бы к добавлению делегата, ссылающегося на метод Writer.Write к уже существующему. Добавить еще одну кнопку - "call delegate", и перенести вызов делегата в метод-обработчик нажатия на эту кнопку. Модифицировать задание так, чтобы при нажатии на кнопку "call delegate" на форме вырабатывалось пользовательское событие MyEvent, на которое по нажатии кнопок "talk" и "write" подписываются соответственно методы Talkrer.SayHi и Writer.Write. Задание 2: Реализовать оконное приложение, демонстрирующее работу многоадресной передачи. Создать кнопки Add и Delete, добавляющие и удаляющие методы в цепочку вызовов соответственно. Указание: взять за основу приведенный пример, добавить обработчики ошибок. Цепочка методов должна собирать строку из слов в поле на форме и выводить полученную строку на экран, используя MessageBox один раз. Информировать пользователя о количестве методов в цепочке. Полезные ссылки: http://rsdn.ru/article/dotnet/delegat.xml