Опубликован: 02.12.2009 | Уровень: специалист | Доступ: платный | ВУЗ: Тверской государственный университет
Лекция 7:

Делегаты. Функциональный тип данных

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >

Пример "Плохая служба"

Как быть, если в списке вызовов есть "плохой" экземпляр, при вызове которого возникает ошибка, приводящая к выбрасыванию исключительной ситуации? Тогда стоящие за ним в очереди экземпляры не будут вызваны, хотя они вполне могли бы выполнить свою часть работы. В этом случае полезно использовать метод GetInvocationList и самому клиенту организовать в цикле поочередный вызов сервисов из списка. Вызов метода следует поместить в охраняемый блок, тогда при возникновении исключительной ситуации в обработчике ситуации можно получить и выдать пользователю всю информацию о нарушителе, а цикл продолжит выполнение очередных методов из списка вызова.

Добавим в класс Combination специальную службу, которая при получении сообщения о пожаре выбрасывает исключение:

//метод, вызывающий исключительную ситуацию
/// <summary>
  /// Модель действий специальной службы
  /// </summary>
  /// <param name="mes">
  /// сообщение о возникшем событии</param>
  /// <returns>результат действий</returns>
  static string specialService(string mes)
  {
      if (mes == "Пожар!")
          throw (new Exception("Специальная служба: Кто виноват?"));
      return (mes + " Специальная служба здесь!");
  }
public static MesToPers Special
    {
 get { return (new MesToPers(specialService)); }
    }

Протестируем ситуацию, в которой возникает исключительная ситуация в процессе вызова одного из методов списка вызовов. Заодно покажем, как, используя метод GetInvocationList, справиться с этой проблемой, так же как и с проблемой потери возвращаемых методами значений.

public void TestBadService()
{
   MesToPers Comb;
   Comb = Combination.Ambulanceman;
      Comb += Combination.Fireman;
   Comb += Combination.Special;
   Comb += Combination.Policeman;
   foreach(MesToPers currentJob in Comb.GetInvocationList())
   {
    try
      {
         Console.WriteLine(currentJob("Пожар!"));
      }
      catch(Exception e)
      {
         Console.WriteLine(e.Message);
         Console.WriteLine(currentJob.Method.Name);
      }
   }
}//BadService

Поясню, как будет работать эта процедура при ее вызове. Вначале две службы нормально отработают, но при вызове третьей службы возникнет исключительная ситуация. Универсальный обработчик Exception перехватит эту ситуацию и напечатает как свойство Message объекта e, так и имя метода, вызвавшего исключительную ситуацию, используя свойство Method объекта, вызвавшего ситуацию. После завершения работы блока обработчика ситуации выполнение программы продолжится, выполнится следующий шаг цикла, и милицейская служба благополучно выполнит свою работу. Вот результаты вывода.

"Специальная служба"

Рис. 6.8. "Специальная служба"

Заметьте, теперь в цикле можно проследить за результатом выполнения каждого метода из списка вызовов, так что ни одно из возвращаемых значений не будет утеряно. Этот пример демонстрирует корректный способ работы со списком вызова.

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

Проекты

  1. Постройте Windows-проект, позволяющий для заданного массива X вычислять некоторую характеристику result, заданную выражением: Метод, вычисляющий значение характеристики result, реализуйте как функцию высшего порядка. Используйте это метод для вычисления таких характеристик массива, как минимум, максимум, сумма и произведение элементов массива.
  2. Постройте класс MyMath, являющийся аналогом класса Math из библиотеки FCL. Задайте в этом клаccе общий метод, позволяющий вычислять различные функции ( sin, cos и другие). Реализуйте этот метод как функцию высшего порядка, передавая ему в качестве аргумента функцию, вычисляющую ak по соответствующей рекуррентной формуле.
  3. Создайте Windows-проект с классом Functions. Класс должен выполнять различные операции над функциями, принадлежащими функциональному типу, заданному делегатом. В число операций класса включите такие методы, как вычисление интеграла, нахождение максимума, минимума, корней функции на заданном интервале, вычисление значения производной функции в заданной точке. В классе-клиенте, использующем сервисы класса Fnctions, используйте анонимные методы и лямбда-выражения. В интерфейсе проекта предусмотрите возможность задания функции как выражением, так и выбором из фиксированного списка.
  4. Создайте Windows-проект с классами Person и Sorting. В классе Sorting предусмотрите разные методы сортировки, заданные функциями высших порядков. Аргументом метода сортировки должна быть функция, позволяющая сравнивать персоны. В клиентском классе предусмотрите построение набора функций, позволяющих сравнивать персоны по разным критериям. Предусмотрите возможность задания таких функций лямбда-выражениями. В интерфейсе проекта предусмотрите возможность сравнения методов сортировки по времени. Постройте метод, вычисляющий время сортировки, как функцию высшего порядка, которой передается в качестве аргумента метод сортировки.
< Лекция 6 || Лекция 7: 123456 || Лекция 8 >
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?

Дмитрий Штаф
Дмитрий Штаф
Россия
Дмитрий Слапогузов
Дмитрий Слапогузов
Россия, Бийск