Главная страница
Навигация по странице:

  • Листинг 2.17. Событие с явным описанием аксессоров

  • Васильев А.Н. Основы программирования на C#. Васильев А. Н. Программирование


    Скачать 5.54 Mb.
    НазваниеВасильев А. Н. Программирование
    АнкорВасильев А.Н. Основы программирования на C
    Дата20.09.2022
    Размер5.54 Mb.
    Формат файлаpdf
    Имя файлаVasilev_Programmirovanie-na-C-dlya-nachinayushchih-Osobennosti-y.pdf
    ТипДокументы
    #686596
    страница9 из 40
    1   ...   5   6   7   8   9   10   11   12   ...   40
    Знакомство с событиями Это неслыханно Что вы здесь делаете Я тут. спим.
    из к/ф Ирония судьбы или с легким паром»
    Представим ситуацию, когда есть некоторая программа, а в этой программе имеется несколько объектов, которые взаимодействуют друг с другом. Мы хотим добиться того, чтобы при стечении определенных условий для одного из объектов другие объекты на это среагировали. Объекты реагируют через свои методы. Специфика ситуации в том, что решение о необходимости вызвать метод объекту поступает извне, от другого объекта. И такое сообщение должно генерироваться автоматически (как только звезды расположились нужным образом. В принципе, для концептуального решения такой задачи нам пригодились бы
    Глава экземпляры делегата сих помощью можно в динамическом режиме устанавливать связи между объектами. Остается открытым вопрос с автоматическим оповещением. И вот в этом случае используется специальный член класса, который называется
    событием.
    Событие описывается в классе. Как и для других членов класса, для событий можно указывать спецификатор уровня доступа (обычно это public
    ). Затем указывается ключевое слово event. После ключевого слова event указывается имя делегата и затем уже название события. Название события — это имя, которое мы даем члену класса, подобно тому как мы даем имя полю или методу. Делегат, который указывается в объявлении события, фактически определяет тип события. Дело в том, что при возникновении события для его обработки могут вызываться экземпляры делегата. В объявлении события мы указываем имя делегата, экземпляры которого могут вызываться для обработки события.
    Таким образом, шаблон объявления события (являющегося открытым членом класса) выглядит следующим образом (жирным шрифтом выделены ключевые элементы шаблона event

    ɞɟɥɟɝɚɬ Например, рассмотрим такое объявление event MyDelegate В данном случае объявляется событие MyEvent, являющееся открытым членом класса (ключевое слово public), а для обработки этого события могут вызываться экземпляры делегата MyDelegate.
    {
    i
    НАЗ А МЕТКУ Если в объявлении события убрать ключевое слово event
    , то фактически получим объявление поля, являющегося ссылкой на экземпляр делегата.
    Все это касается формальной стороны — объявления события. Но остается открытым вопрос о том, что с событием можно делать. Есть две концептуальные задачи, которые решаются при работе с событиями. Во-первых, событие можно вызвать (или сгенерировать). Во-вторых, событие можно связать с экземплярами делегата, которые будут автоматически вызываться при генерировании (возникновении) события. Начнем со второй задачи
    Делегаты и события НАЗ А МЕТКУ Связанные с событием методы, которые вызываются при возникновении события, называются обработчиками события.
    Для добавления ссылки на экземпляр делегата, который будет вызываться при генерировании события, этот экземпляр (ссылка на него) добавляется с помощью оператора += (только сокращенная форма. Используется команда вида
    ɫɨɛɵɬɢɟ+=ɷɤɡɟɦɩɥɹɪ. На практике вместо ссылки на экземпляр делегата можно использовать ссылку на метод, соответствующий делегату, с которым объявлено событие. То есть можно использовать команду вида
    ɫɨɛɵɬɢɟ+=ɦɟɬɨɞ. После выполнения такой команды, если произойдет событие, то автоматически будет вызван соответствующий метод ПОДРОБНОСТИ bПри добавлении в событие ссылки на экземпляр делегата или ссылки на метод с помощью оператора
    +=
    вызывается специальный ме- тод-аксессор. При этом ожидается, что в правой части оператора указана ссылка на экземпляр делегата. Для запоминания этой ссылки выделяется специальная переменная типа делегата. Если вместо ссылки на экземпляр делегата указана ссылка на метод, то получается, что переменной делегата в качестве значения присваивается указатель на метод. В этом случае автоматически создается экземпляр делегата, который ссылается на метод. Ссылка на этот экземпляр записывается в переменную делегата.
    Если мы хотим удалить ссылку на экземпляр делегата из события, то для этой цели используется оператор -= (тоже только сокращенная форма. Ситуация такая же, как и с оператором +=: мы можем использовать команды вида
    ɫɨɛɵɬɢɟ-=ɷɤɡɟɦɩɥɹɪ или ɫɨɛɵɬɢɟ-=ɦɟɬɨɞ. То есть вместо ссылки на экземпляр мы можем использовать ссылку на метод.
    Итак, при возникновении события автоматически вызываются экземпляры делегатов, связанные с этим событием. Но как сгенерировать событие Ответ простой его нужно вызвать подобно вызову метода. Указываются имя события и круглые скобки — если нужно, то с аргументами. Количество и тип аргументов определяются делегатом, указанным в объявлении события. Важная особенность события связана стем, что вызвать (сгенерировать) событие можно только внутри класса.
    Глава 2
    114
    Сгенерировать событие через ссылку на объект класса не получится, даже если событие в классе объявлено с ключевым словом public. Через объект доступны только операции += и -=, с помощью которых в событие добавляются и удаляются ссылки на экземпляры делегата НАЗ А МЕТКУ Спецификатор уровня доступа в объявлении события определяет наследуемость свойства в производном классе и доступность операций и
    -=
    за пределами класса. В любом случае, если в классе есть событие, то вызвать (сгенерировать) событие можно только в программном коде этого класса.
    Небольшой пример, в котором используются события, представлен в листинге 2.16.
    
    Листинг 2.16. Знакомство с событиями System;
    //
    Ɉɛɴɹɜɥɟɧɢɟ ɞɟɥɟɝɚɬɚ:
    delegate void MyDelegate(string txt);
    //
    Ʉɥɚɫɫ ɫ ɫɨɛɵɬɢɟɦ:
    class MyClass{
    //
    Ɉɛɴɹɜɥɟɧɢɟ ɫɨɛɵɬɢɹ:
    public event MyDelegate MyEvent;
    //
    Ɇɟɬɨɞ ɞɥɹ ɝɟɧɟɪɢɪɨɜɚɧɢɹ ɫɨɛɵɬɢɹ:
    public void RaiseMyEvent(string txt){
    //
    ȿɫɥɢ ɞɥɹ ɫɨɛɵɬɢɹ ɩɪɟɞɭɫɦɨɬɪɟɧɵ ɨɛɪɚɛɨɬɱɢɤɢ:
    if(MyEvent!=null){
    //
    Ƚɟɧɟɪɢɪɨɜɚɧɢɟ ɫɨɛɵɬɢɹ:
    MyEvent(txt);
    }
    }
    }
    //
    Ʉɥɚɫɫ:
    class Alpha{
    Делегаты и события //
    Ɍɟɤɫɬɨɜɨɟ ɩɨɥɟ:
    public string name;
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public Alpha(string txt){
    name=txt;
    }
    //
    Ɇɟɬɨɞ ɨɬɨɛɪɚɠɚɟɬ ɫɨɨɛɳɟɧɢɟ:
    public void show(string msg){
    Console.WriteLine(
    ƎɈɛɴɟɤɬ Ǝ+name+Ǝ:Ǝ);
    Console.WriteLine(msg);
    }
    }
    //
    Ʉɥɚɫɫ ɫ ɝɥɚɜɧɵɦ ɦɟɬɨɞɨɦ:
    class EventDemo{
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɫ ɫɨɛɵɬɢɟɦ:
    MyClass obj=new MyClass();
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɨɜ:
    Alpha A=new Alpha(
    ƎAƎ);
    Alpha B=new Alpha(
    ƎBƎ);
    //
    ɉɨɩɵɬɤɚ ɫɝɟɧɟɪɢɪɨɜɚɬɶ ɫɨɛɵɬɢɟ:
    obj.RaiseMyEvent(
    Ǝ1-ɟ ɫɨɛɵɬɢɟƎ);
    //
    Ⱦɨɛɚɜɥɟɧɢɟ ɨɛɪɚɛɨɬɱɢɤɚ ɞɥɹ ɫɨɛɵɬɢɹ:
    obj.MyEvent+=A.show;
    //
    Ƚɟɧɟɪɢɪɨɜɚɧɢɟ ɫɨɛɵɬɢɹ:
    obj.RaiseMyEvent(
    Ǝ2-ɟ ɫɨɛɵɬɢɟƎ);
    Console.WriteLine();
    //
    Ⱦɨɛɚɜɥɟɧɢɟ ɨɛɪɚɛɨɬɱɢɤɚ ɞɥɹ ɫɨɛɵɬɢɹ:
    obj.MyEvent+=B.show;
    //
    Ƚɟɧɟɪɢɪɨɜɚɧɢɟ ɫɨɛɵɬɢɹ:
    obj.RaiseMyEvent(
    Ǝ3-ɟ ɫɨɛɵɬɢɟƎ);
    Глава 2
    116
    Console.WriteLine();
    //
    ɍɞɚɥɟɧɢɟ ɦɟɬɨɞɚ ɢɡ ɫɩɢɫɤɚ ɨɛɪɚɛɨɬɱɢɤɨɜ ɫɨɛɵɬɢɹ:
    obj.MyEvent-=A.show;
    //
    Ƚɟɧɟɪɢɪɨɜɚɧɢɟ ɫɨɛɵɬɢɹ:
    obj.RaiseMyEvent(
    Ǝ4-ɟ ɫɨɛɵɬɢɟƎ);
    Console.WriteLine();
    //
    ɍɞɚɥɟɧɢɟ ɦɟɬɨɞɨɜ ɢɡ ɫɩɢɫɤɚ ɨɛɪɚɛɨɬɱɢɤɨɜ ɫɨɛɵɬɢɹ:
    obj.MyEvent-=A.show;
    obj.MyEvent-=B.show;
    //
    ɉɨɩɵɬɤɚ ɫɝɟɧɟɪɢɪɨɜɚɬɶ ɫɨɛɵɬɢɟ:
    obj.RaiseMyEvent(
    Ǝ5-ɟ ɫɨɛɵɬɢɟƎ);
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ:
    MyDelegate md=A.show;
    //
    Ⱦɨɛɚɜɥɟɧɢɟ ɦɟɬɨɞɚ ɜ ɫɩɢɫɨɤ ɜɵɡɨɜɨɜ
    //
    ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ:
    md+=B.show;
    //
    Ⱦɨɛɚɜɥɟɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ ɜ ɫɩɢɫɨɤ
    //
    ɨɛɪɚɛɨɬɱɢɤɨɜ ɫɨɛɵɬɢɹ:
    obj.MyEvent+=md;
    //
    Ƚɟɧɟɪɢɪɨɜɚɧɢɟ ɫɨɛɵɬɢɹ:
    obj.RaiseMyEvent(
    Ǝ6-ɟ ɫɨɛɵɬɢɟƎ);
    Результат выполнения программы представлен ниже Результат выполнения программы (из листинга 2.16)

    Ɉɛɴɟɤɬ A:
    2-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ A:
    3-
    ɟ ɫɨɛɵɬɢɟ
    Делегаты и события B:
    3-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ B:
    4-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ A:
    6-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ B:
    6-
    ɟ В программе объявлен делегат MyDelegate. Экземпляры делегата могут ссылаться на методы, имеющие один текстовый аргумент и не возвращающие результат.
    Класс MyClass содержит объявление события MyEvent. Оно описано с ключевым словом event, типом события указан делегат MyDelegate. Это означает, что для обработки события могут использоваться методы, сигнатура которых соответствует характеристикам делегата
    MyDelegate
    : у метода должен быть текстовый аргумент, и метод не должен возвращать результат. Еще в классе MyClass описан открытый метод) с текстовым аргументом (обозначен как txt). Метод предназначен для генерирования события MyEvent. В теле метода с помощью условного оператора проверяется условие MyEvent!=null, и если оно истинно, то командой MyEvent(txt) генерируется событие
    MyEvent
    . После генерирования события командой MyEvent(txt) автоматически вызываются все методы, зарегистрированные в качестве обработчиков данного события. Каждому из методов аргументом передается текстовое значение txt.
    q
    ПОДРОБНОСТИ bЗачем нам нужен метод
    RaiseMyEvent()
    ? Понятно, что событие генерируется при выполнении команды
    MyEvent(txt)
    . Но дело в том, что вызвать (сгенерировать) событие командой
    MyEvent(txt)
    мы можем только в теле класса. Поэтому мы описываем открытый метод, который можно вызвать через ссылку на объект класса
    MyClass
    . А при вызове метода
    RaiseMyEvent()
    уже будет
    Глава 2
    118
    сгенерировано событие
    MyEvent
    (для объекта, из которого вызывается метод Если при генерировании события окажется, что список обработчиков для этого события пустой, то возникнет ошибка. Поэтому перед генерированием события командой
    MyEvent(txt)
    в теле метода
    RaiseMyEvent()
    сначала проверяется условие
    MyEvent!=null
    . Оно истинно, если список обработчиков для события непустой. Только в этом случае генерируется событие.
    В классе Alpha есть открытое текстовое поле name. Конструктор с одним текстовым аргументом позволяет присвоить значение полю при создании объекта. Также в классе есть метод show(). Метод не возвращает результат и имеет один текстовый аргумент (обозначен как msg). Таким образом, метод show() полностью соответствует характеристикам делегата и может быть использован как обработчик события
    MyEvent
    . В теле метода show() командой Console.WriteLine(
    ƎɈɛɴ-
    ɟɤɬ Ǝ+name+Ǝ:Ǝ) отображается значение поля name объекта, из которого вызывается метода затем командой Console.WriteLine(msg) отображается значение аргумента, переданного методу.
    В главном методе программы мы создаем объект obj класса MyClass, а также объекты A и B класса Сначала командой obj.RaiseMyEvent(
    Ǝ1-ɟ ɫɨɛɵɬɢɟƎ) мы пытаемся сгенерировать событие MyEvent для объекта obj. Нона момент выполнения данной команды список обработчиков для события MyEvent объекта obj пуст, поэтому ничего не происходит. Затем командой obj.MyEvent+=A.show в качестве обработчика события регистрируется метод show() объекта A. Поэтому после генерирования события командой obj.RaiseMyEvent(
    Ǝ2-ɟ ɫɨɛɵɬɢɟƎ) из объекта A вызывается метод show() с аргументом
    Ǝ2-ɟ Наследующем этапе командой obj.MyEvent+=B.show для события обработчиком дополнительно регистрируется еще и метод show()
    объекта B. Поэтому при генерировании события командой obj.RaiseMyEvent(
    Ǝ3-ɟ ɫɨɛɵɬɢɟƎ) из объектов A и B с аргументом
    Ǝ3-ɟ ɫɨɛɵɬɢɟƎ последовательно вызывается метод Командой obj.MyEvent-=A.show метод show() объекта A удаляется из списка обработчиков для события MyEvent объекта obj (у события остается один обработчик — метод show() объекта B). При генерировании события командой obj.RaiseMyEvent(
    Ǝ4-ɟ ɫɨɛɵɬɢɟƎ)
    Делегаты и события
    119
    с аргументом
    Ǝ4-ɟ ɫɨɛɵɬɢɟƎ вызывается метод show() объекта B. Далее командами obj.MyEvent-=A.show и obj.MyEvent-=B.show из списка обработчиков события удаляются методы show() объектов A и B. Причем на момент выполнения команды obj.MyEvent-=A.show метода show() объекта A в списке обработчиков нет, так что здесь имеет место попытка удалить отсутствующий в списке метод. Но, как видим, к ошибке это не приводит. А общий итог такой, что список обработчиков события MyEvent объекта obj становится пустым. Как следствие, при выполнении команды obj.RaiseMyEvent(
    Ǝ5-ɟ ɫɨɛɵɬɢɟƎ) ничего не происходит (сообщения в консольном окне не появляются).
    Как отмечалось ранее, в список обработчиков могут добавляться экземпляры делегатов или методы. Методы мы уже добавляли. На финальном этапе прибегнем к помощи экземпляров делегата MyDelegate. Командой создается экземпляр md, ив список вызовов делегата добавляется ссылка на метод show() объекта A. Командой md+=B.show туда же добавляется ссылка на метод show() объекта B. А затем командой obj.MyEvent+=md в список обработчиков события
    MyEvent объекта obj добавляется делегат md. При генерировании события командой obj.RaiseMyEvent(
    Ǝ6-ɟ ɫɨɛɵɬɢɟƎ) вызывается экземпляр делегата md с аргументом
    Ǝ6-ɟ ɫɨɛɵɬɢɟƎ. Вызов этого экземпляра означает вызов метода show() из объектов A и На первый взгляд может показаться, что между событием и экземпляром делегата принципиальной разницы нет. Правда мы не можем вызвать (или сгенерировать) событие вне пределов класса, а при операциях с событием можем использовать только операторы += и -=: во всем остальном события и экземпляры делегатов действительно похожи. Но разница между ними все же имеется, причем принципиальная. Событие от экземпляра делегата отличается примерно также, как свойство отличается от текстового поля (роль текстового поля в данном случае играет ссылка на экземпляр делегата. За событием спрятана ссылка на экземпляр делегата и два метода-аксессора, которые отвечают за добавление методов в список обработчиков события и за удаление методов из списка обработчиков события. Если в классе объявлено событие, то все это богатство (ссылка на экземпляр делегата и методы-аксессо- ры) создается автоматически, без нашего участия. Номы можем реализовать все самостоятельно, в явном виде.
    Событие можно объявлять с явным описанием аксессоров. Аксессор, вызываемый при добавлении (с помощью оператора +=) метода в список
    Глава обработчиков события, называется add. Аксессор, который вызывается при удалении (с помощью оператора -=) ссылки на метод из списка обработчиков события, называется remove. Ключевое слово value обозначает значение (ссылка на метод или экземпляр делегата, находящееся в правой части выражения с оператором += или -=. Общий шаблон объявления события в таком случае имеет следующий вид (жирным шрифтом выделены ключевые элементы шаблона
    event
    ɞɟɥɟɝɚɬ ɫɨɛɵɬɢɟ{
    add{
    //
    Ʉɨɦɚɧɞɵ add-ɚɤɫɟɫɫɨɪɚ
    }
    remove{
    //
    Ʉɨɦɚɧɞɵ Фактически событие в этом случае описывается как свойство, только вместо get-аксессора и set-аксессора используются add-аксессор и remove-аксессор. Преимущество такого способа описания события в том, что мы можем изменить используемый по умолчанию алгоритм добавления (удаления) методов в список (из списка) обработчиков события. Как иллюстрацию к сказанному рассмотрим аналог предыдущей программы, но только на этот раз для реализации события мы воспользуемся явным описанием аксессоров, а для записи списка обработчиков события будем использовать закрытое поле, являющееся ссылкой на экземпляр делегата. Интересующий нас программный код представлен в листинге 2.17.
    
    Листинг 2.17. Событие с явным описанием аксессоров
    using System;
    //
    Ɉɛɴɹɜɥɟɧɢɟ ɞɟɥɟɝɚɬɚ:
    delegate void MyDelegate(string txt);
    //
    Ʉɥɚɫɫ ɫ ɫɨɛɵɬɢɟɦ:
    class MyClass{
    //
    Ɂɚɤɪɵɬɨɟ ɩɨɥɟ (ɫɫɵɥɤɚ ɧɚ ɷɤɡɟɦɩɥɹɪ ɞɟɥɟɝɚɬɚ)
    //
    ɞɥɹ ɪɟɚɥɢɡɚɰɢɢ ɫɩɢɫɤɚ ɨɛɪɚɛɨɬɱɢɤɨɜ ɫɨɛɵɬɢɹ:
    Делегаты и события private MyDelegate myevent;
    //
    Ɉɛɴɹɜɥɟɧɢɟ ɫɨɛɵɬɢɹ (ɫ ɨɩɢɫɚɧɢɟɦ ɚɤɫɟɫɫɨɪɨɜ):
    public event MyDelegate MyEvent{
    //
    Ⱥɤɫɟɫɫɨɪ ɞɥɹ ɞɨɛɚɜɥɟɧɢɹ ɦɟɬɨɞɚ ɜ ɫɩɢɫɨɤ
    //
    ɨɛɪɚɛɨɬɱɢɤɨɜ ɫɨɛɵɬɢɹ:
    add{
    //
    Ⱦɨɛɚɜɥɟɧɢɟ ɫɫɵɥɤɢ ɧɚ ɦɟɬɨɞ ɜ ɫɩɢɫɨɤ ɜɵɡɨɜɨɜ
    //
    ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ:
    myevent+=value;
    }
    //
    Ⱥɤɫɟɫɫɨɪ ɞɥɹ ɭɞɚɥɟɧɢɹ ɦɟɬɨɞɚ ɢɡ ɫɩɢɫɤɚ
    //
    ɨɛɪɚɛɨɬɱɢɤɨɜ ɫɨɛɵɬɢɹ:
    remove{
    //
    ɍɞɚɥɟɧɢɟ ɫɫɵɥɤɢ ɧɚ ɦɟɬɨɞ ɢɡ ɫɩɢɫɤɚ ɜɵɡɨɜɨɜ
    //
    ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ:
    myevent-=value;
    }
    }
    //
    Ɇɟɬɨɞ ɞɥɹ ɝɟɧɟɪɢɪɨɜɚɧɢɹ ɫɨɛɵɬɢɹ:
    public void RaiseMyEvent(string txt){
    //
    ȿɫɥɢ ɞɥɹ ɫɨɛɵɬɢɹ ɩɪɟɞɭɫɦɨɬɪɟɧɵ ɨɛɪɚɛɨɬɱɢɤɢ:
    if(myevent!=null){
    //
    Ƚɟɧɟɪɢɪɨɜɚɧɢɟ ɫɨɛɵɬɢɹ
    // (
    ɜɵɡɨɜ ɷɤɡɟɦɩɥɹɪɚ ɞɟɥɟɝɚɬɚ):
    myevent(txt);
    }
    }
    }
    //
    Ʉɥɚɫɫ:
    class Alpha{
    public string name;
    public Alpha(string txt){
    Глава 2
    122
    name=txt;
    }
    public void show(string msg){
    Console.WriteLine(
    ƎɈɛɴɟɤɬ Ǝ+name+Ǝ:Ǝ);
    Console.WriteLine(msg);
    }
    }
    //
    Ʉɥɚɫɫ ɫ ɝɥɚɜɧɵɦ ɦɟɬɨɞɨɦ:
    class EventDemo{
    static void Main(){
    MyClass obj=new MyClass();
    Alpha A=new Alpha(
    ƎAƎ);
    Alpha B=new Alpha(
    ƎBƎ);
    obj.RaiseMyEvent(
    Ǝ1-ɟ ɫɨɛɵɬɢɟƎ);
    obj.MyEvent+=A.show;
    obj.RaiseMyEvent(
    Ǝ2-ɟ ɫɨɛɵɬɢɟƎ);
    Console.WriteLine();
    obj.MyEvent+=B.show;
    obj.RaiseMyEvent(
    Ǝ3-ɟ ɫɨɛɵɬɢɟƎ);
    Console.WriteLine();
    obj.MyEvent-=A.show;
    obj.RaiseMyEvent(
    Ǝ4-ɟ ɫɨɛɵɬɢɟƎ);
    Console.WriteLine();
    obj.MyEvent-=A.show;
    obj.MyEvent-=B.show;
    obj.RaiseMyEvent(
    Ǝ5-ɟ ɫɨɛɵɬɢɟƎ);
    MyDelegate md=A.show;
    md+=B.show;
    obj.MyEvent+=md;
    obj.RaiseMyEvent(
    Ǝ6-ɟ ɫɨɛɵɬɢɟƎ);
    }
    }
    Делегаты и события
    123
    Результат выполнения программы точно такой же, как ив предыдущем случае Результат выполнения программы (из листинга 2.17)

    Ɉɛɴɟɤɬ A:
    2-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ A:
    3-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ B:
    3-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ B:
    4-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ A:
    6-
    ɟ ɫɨɛɵɬɢɟ
    Ɉɛɴɟɤɬ B:
    6-
    ɟ В этом примере, по сравнению с программой из листинга 2.16, изменилось только описание метода MyClass. Теперь в классе появилось закрытое поле myevent типа MyDelegate. Это ссылка на экземпляр делегата, через который реализуется список обработчиков для события
    MyEvent
    . Событие описывается таким блоком кода event MyDelegate MyEvent{
    add{
    myevent+=value;
    }
    remove{
    myevent-=value;
    }
    }
    Глава Код add-аксессора выполняется при добавлении новой ссылки в список обработчиков для события MyEvent с помощью оператора +=. В этом случае командой myevent+=value соответствующая ссылка на метод или экземпляр делегата (обозначается ключевым словом value) добавляется в экземпляр делегата myevent. Код remove-аксессора выполняется при удалении ссылки на метод или экземпляр делегата из списка обработчиков события MyEvent. В этом случае командой myevent-=value ссылка, указанная справа от оператора -=, удаляется из экземпляра делегата Несколько изменился код метода RaiseMyEvent(), предназначенного для генерирования события. Теперь в теле метода с помощью условного оператора проверяется условие myevent!=null (поле myevent содержит ссылку на экземпляр делегата, и если условие истинно, то с помощью вызова соответствующего экземпляра делегата происходит генерирование события».
    Все остальное происходит также, как ив программе из листинга 2.16.
    {
    1   ...   5   6   7   8   9   10   11   12   ...   40


    написать администратору сайта