Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет: Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.
Как активировать код? |
Интерфейсы, делегаты, события в C#
Методы Combine() и Remove()
Это статические методы, способные получать новый делегат как объединение списков двух делегатов одного и того же типа, или получать новый делегат с усеченным списком при тех же условиях. Методы могут использоваться вместо перегруженных операций ' += ' или ' -= ' при последовательном изменении списка одиночными функциями по синтаксису
MyDelegate del; del = new MyDelegate(obj.Handler1); del += new MyDelegate(obj.Handler2); // Или del = new MyDelegate(obj.Handler1); del = (MyDelegate)Delegate.Combine(del, new MyDelegate(obj.Handler2));
using System; namespace Test { class Handler { // Функции public void Handler1() { Console.WriteLine("Вызов Handler1()"); } public void Handler2() { Console.WriteLine("Вызов Handler2()"); } } // Вызывающая сторона class MyClass { public static string Title = "Применение Combine() и Remove()"; // Объявляем делегат как член класса delegate void MyDelegate(); public MyClass() { // Создаем объект Handler obj=new Handler(); // Формируем список объекта-делегата из 2 вызовов MyDelegate del1 = new MyDelegate(obj.Handler1); del1 += new MyDelegate(obj.Handler1); // Еще один делегат того же типа из 3 вызовов MyDelegate del2 = new MyDelegate(obj.Handler2); del2 += obj.Handler2; // Упрощенный синтаксис del2 = del2 + obj.Handler2; // То же самое // Новый делегат из 5 вызовов MyDelegate del3 = (MyDelegate)Delegate.Combine(del1, del2); // Вызываем 5 функций del3(); Console.WriteLine(); // Вновь формируем делегаты del1 = new MyDelegate(obj.Handler1); del1 += obj.Handler2; // Усекаем первый список вторым del2 = (MyDelegate)Delegate.Remove(del3, del1); // Вызываем оставшиеся 3 функции del2(); } } // Запуск class Program { static void Main() { // Настройка консоли Console.Title = MyClass.Title; Console.ForegroundColor = ConsoleColor.White; Console.CursorVisible = false; Console.WindowWidth = 33; Console.WindowHeight = 10; new MyClass();// Исполняем Console.ReadLine(); } } }Листинг 10.16 . Применение методов Combine() и Remove()
События в C#
Рассылка сообщений с помощью делегата
Чтобы любые объекты могли обмениваться информацией, они должны разговаривать на одном языке. В случае объектно-ориентированного программирования таким условием является одинаковый прототип функций, определяемый делегатом. Многоадресная работа делегата удобна тем, что можно послать одинаковое сообщение сразу нескольким объектам, функции которых зарегистрированы в списке делегата как обработчики этого сообщения. Список делегата можно назвать по-разному:
- список вызываемых функций,
- список обработчиков,
- список адресатов,
- список получателей и т.д.
Напомним, что если список адресатов пуст, то самого объекта-делегата не существует и ссылка на него имеет значение null. Без проверки этого обстоятельства при попытке вызова адресатов пустой ссылкой-делегатом будет сгенерировано стандартное исключение NullReferenceException.
Вот пример однонаправленной рассылки сообщения
using System; namespace Test { // Образец сообщения определяется делегатом delegate void Message(string message); // Источник сообщения class SourceMessage { // Общедоступное поле ссылки на объект-делегат, // который наполнится указателями // на функции в классах-получателях public Message mail; // Необязательное поле с рассылаемым сообщением public string message; // Разослать сообщение - функция диспетчеризации public void DispatchMessage(string mess) { // Сохраняем внешнее сообщение во внутреннем поле message = mess; // Инициируем рассылку сообщения всем, // кто зарегистрировался в объекте-делегате if (mail != null) // Если не пустой делегат mail(mess); } } // Получатель сообщения class Addressee1 { // Функции public void Handler(string message) { Console.WriteLine("Addressee1 получил:" + "\n\t\"{0}\"", message); } } // Получатель сообщения class Addressee2 { // Функции public void Handler(string message) { Console.WriteLine("Addressee2 получил:" + "\n\t\"{0}\"", message); } } // Вызывающая сторона class MyClass { static public string Title = "Рассылка сообщений делегатом"; public MyClass() { // Создаем объекты источника и получателей сообщения SourceMessage source = new SourceMessage(); Addressee1 obj1 = new Addressee1(); Addressee2 obj2 = new Addressee2(); // Формируем список вызовов объекта-делегата source.mail += new Message(obj1.Handler); source.mail += new Message(obj2.Handler); // Рассылаем сообщение напрямую через делегат source.mail("Первое сообщение"); Console.WriteLine(); // Рассылаем сообщение через функцию диспетчеризации source.DispatchMessage("Второе сообщение"); } } // Запуск class Program { static void Main() { // Настройка консоли Console.Title = MyClass.Title; Console.ForegroundColor = ConsoleColor.White; Console.CursorVisible = false; Console.WindowWidth = 32; Console.WindowHeight = 10; new MyClass();// Исполняем Console.ReadLine(); } } }Листинг 10.17 . Однонаправленная передача сообщений объектам с помощью делегата
Обратите внимание, что при добавлении в делегат первой ссылки на функцию нам не обязательно использовать операцию ' = ', а можно и ' += ', несмотря на то, что делегат еще пустой.
В классе-источнике сообщения SourceMessage мы объявили два общедоступных поля: ссылку mail на объект-делегат и переменную message для хранения сообщения внутри класса. Поле-переменная message для работы программы не нужна, но мы ее ввели просто для того, чтобы сравнить представления в панели Class View.
Если теперь посмотреть на состав класса SourceMessage через панель Class View, то мы не сможем различить две этих переменные - обычные поля, да и только. Но ведь поле mail не выполняет роль хранителя ссылки на обычный экземпляр класса или структуры, а предназначено для создания механизма адресации функций.