На этом шаге мы рассмотрим понятие события и особенности его использования.
Представим ситуацию, когда есть некоторая программа, а в этой программе имеется несколько объектов, которые "взаимодействуют" друг с другом. Мы хотим добиться того, чтобы при стечении определенных условий для одного из объектов другие объекты на это "среагировали". Объекты "реагируют" через свои методы. Специфика ситуации в том, что решение о необходимости вызвать метод объекту поступает извне, от другого объекта. И такое сообщение должно генерироваться автоматически (как только "звезды расположились нужным образом"). В принципе, для концептуального решения такой задачи нам пригодились бы экземпляры делегата: с их помощью можно в динамическом режиме устанавливать связи между объектами. Остается открытым вопрос с автоматическим оповещением. И вот в этом случае используется специальный член класса, который называется событием.
Событие описывается в классе. Как и для других членов класса, для событий можно указывать спецификатор уровня доступа (обычно это public). Затем указывается ключевое слово event. После ключевого слова event указывается имя делегата и затем уже название события. Название события - это имя, которое мы даем члену класса, подобно тому как мы даем имя полю или методу. Делегат, который указывается в объявлении события, фактически определяет "тип" события. Дело в том, что при возникновении события для его обработки могут вызываться экземпляры делегата. В объявлении события мы указываем имя делегата, экземпляры которого могут вызываться для обработки события.
Таким образом, шаблон объявления события (являющегося открытым членом класса) выглядит следующим образом:
public event делегат событие;
Например, рассмотрим такое объявление:
public event MyDelegate MyEvent;
В данном случае объявляется событие MyEvent, являющееся открытым членом класса (ключевое слово public), а для обработки этого события могут вызываться экземпляры делегата MyDelegate.
Все это касается формальной стороны - объявления события. Но остается открытым вопрос о том, что с событием можно делать. Есть две концептуальные задачи, которые решаются при работе с событиями. Во-первых, событие можно вызвать (или сгенерировать). Во-вторых, событие можно связать с экземплярами делегата, которые будут автоматически вызываться при генерировании (возникновении) события. Начнем со второй задачи.
Для добавления ссылки на экземпляр делегата, который будет вызываться при генерировании события, этот экземпляр (ссылка на него) добавляется с помощью оператора += (только сокращенная форма!). Используется команда вида
событие += экземпляр .
событие += метод .
Если мы хотим удалить ссылку на экземпляр делегата из события, то для этой цели используется оператор -= (тоже только сокращенная форма!). Ситуация такая же, как и с оператором +=: мы можем использовать команды вида
событие -= экземпляр
событие-=метод .
Итак, при возникновении события автоматически вызываются экземпляры делегатов, связанные с этим событием. Но как сгенерировать событие? Ответ простой: его нужно вызвать подобно вызову метода. Указываются имя события и круглые скобки - если нужно, то с аргументами. Количество и тип аргументов определяются делегатом, указанным в объявлении события. Важная особенность события связана с тем, что вызвать (сгенерировать) событие можно только внутри класса.
Сгенерировать событие через ссылку на объект класса не получится, даже если событие в классе объявлено с ключевым словом public. Через объект доступны только операции += и -=, с помощью которых в событие добавляются и удаляются ссылки на экземпляры делегата.
На следующем шаге мы продолжим изучение этого вопроса.