Выбрать главу

Операции "+" и "-"

Наряду с методами, над делегатами определены и две операции: "+" и "-", которые являются более простой формой записи добавления делегатов в список вызовов и удаления из списка. Операции заменяют собой методы Combine и Remove. Выше написанные присваивания объекту dell с помощью этих операций могут быть переписаны в виде:

del1 +=del2;

del1 — =del2;

Как видите, запись становится проще, исчезает необходимость в задании явного приведения к типу. Ограничения на del1 и del2, естественно, остаются те же, что и для методов Combine и Remove.

Пример "Комбинирование делегатов"

Рассмотрим следующую ситуацию. Пусть есть городские службы: милиция, скорая помощь, пожарные. Каждая из служб по-своему реагируют на события, происходящие в городе. Построим примитивную модель жизни города, в которой случаются события и сообщения о них посылаются службам. В последующей лекции эта модель будет развита. Сейчас она носит формальный характер, демонстрируя, главным образом, работу с делегатами, заодно поясняя ситуации, в которых разумно комбинирование делегатов.

Начнем с построения класса с именем Combination, где, следуя уже описанной технологии, введем делегатов как закрытые свойства, доступ к которым идет через процедуру-свойство get. Три делегата одного класса будут описывать действия трех городских служб. Класс будет описываться ранее введенным делегатом MesToPers, размещенным в пространстве имен проекта. Вот программный код, в котором описаны функции, задающие действия служб:

class Combination

{

     private static void policeman (string mes)

     {

         //анализ сообщения

         if(mes =="Пожар!")

              Console.WriteLine(mes + " Милиция ищет виновных!");

         else

              Console.WriteLine(mes +" Милиция здесь!");

      }

      private static void ambulanceman(string mes)

      {

           if(mes =="Пожар!")

               Console.WriteLine(mes + " Скорая спасает пострадавших!");

           else

                Console.WriteLine(mes + " Скорая помощь здесь!");

       }

       private static void fireman(string mes)

       {

            if(mes =="Пожар!")

                 Console.WriteLine(mes + " Пожарные тушат пожар!");

            else

                 Console.WriteLine(mes + " Пожарные здесь!");

       }

}

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

public static MesToPers Policeman

{

    get {return (new MesToPers(policeman));}

}

public static MesToPers Fireman

{

    get {return (new MesToPers(fireman));}

}

public static MesToPers Ambulanceman

(

    get (return (new MesToPers(ambulanceman));}

}

Три статических открытых свойства — Policeman, Fireman, Ambulanceman — динамически создают экземпляры класса MesToPers, связанные с соответствующими закрытыми функциями класса.

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

public void TestSomeServices()

{

   MesToPers Comb;

   Comb = (MesToPers)Delegate.Combine(Combination.Ambulanceman,

          Combination.Policeman);

    Comb = (MesToPers)Delegate.Combine(Comb,Combination.Fireman);

          Comb("Пожар!");

Вначале объявляется без инициализации функциональная переменная Comb, которой в следующем операторе присваивается ссылка на экземпляр делегата, созданного методом Combine, чей список вызова содержит ссылки на экземпляры делегатов Ambulanceman и Policeman. Затем к списку вызовов экземпляра Comb присоединяется новый кандидат Fireman. При вызове делегата Comb ему передается сообщение "Пожар!". В результате вызова Comb поочередно запускаются все три экземпляра входящие в список, каждому из которых передается сообщение.

Давайте теперь начнем поочередно отключать делегатов, вызывая затем Comb с новыми сообщениями:

Comb = (MesToPers)Delegate.Remove (Comb,Combination.Policeman);

//Такое возможно: попытка отключить не существующий элемент

Comb = (MesToPers)Delegate.Remove (Comb,Combination.Policeman);

Comb ("Через 30 минут!");

Comb = (MesToPers)Delegate.Remove(Comb,Combination.Ambulanceman);