Как видите, обработчик вызывается лишь в том случае, если событие SomeEvent
не является пустым. А поскольку интерес к событию должен быть зарегистрирован в других частях программы, чтобы получать уведомления о нем, то метод OnSomeEvent()
может быть вызван до регистрации любого обработчика события. Но во избежание вызова по пустой ссылке делегат события должен быть проверен, чтобы убедиться в том, что он не является пустым.
В классе EventDemo
создается обработчик событий Handler()
. В данном простом примере обработчик событий просто выводит сообщение, но другие обработчики могут выполнять более содержательные функции. Далее в методе Main()
создается объект класса события MyEvent
, a Handler()
регистрируется как обработчик этого события, добавляемый в список.
MyEvent evt = new MyEvent();
// Добавить метод Handler() в список событий,
evt.SomeEvent += Handler;
Обратите внимание на то, что обработчик добавляется в список с помощью оператора +=
. События поддерживают только операторы +=
и -=
. В данном случае метод Handler()
является статическим, но в качестве обработчиков событий могут также служить методы экземпляра.
И наконец, событие запускается, как показано ниже.
// Запустить событие,
evt.OnSomeEvent();
Вызов метода OnSomeEvent()
приводит к вызову всех событий, зарегистрированных обработчиком. В данном случае зарегистрирован только один такой обработчик, но их может быть больше, как поясняется в следующем разделе.
Как и делегаты, события поддерживают групповую адресацию. Это дает возможность нескольким объектам реагировать на уведомление о событии. Ниже приведен пример групповой адресации события.
// Продемонстрировать групповую адресацию события,
using System;
// Объявить тип делегата для события,
delegate void MyEventHandler() ;
// Объявить делегат, содержащий событие,
class MyEvent {
public event MyEventHandler SomeEvent;
// Этот метод вызывается для запуска события,
public void OnSomeEvent() {
if(SomeEvent != null)
SomeEvent();
}
}
class X {
public void Xhandler() {
Console.WriteLine("Событие получено объектом класса X");
}
}
class Y {
public void Yhandler() {
Console.WriteLine("Событие получено объектом класса Y");
}
}
class EventDemo2 {
static void Handler() {
Console.WriteLine("Событие получено объектом класса EventDemo");
}
static void Main() {
MyEvent evt = new MyEvent();
X xOb = new X();
Y yOb = new Y();
// Добавить обработчики в список событий.
evt.SomeEvent += Handler;
evt.SomeEvent += xOb.Xhandler;
evt.SomeEvent += yOb.Yhandler;
// Запустить событие, evt.OnSomeEvent() ;
Console.WriteLine() ;
// Удалить обработчик.
evt.SomeEvent -= xOb.Xhandler;
evt.OnSomeEvent() ;
}
}
При выполнении кода этого примера получается следующий результат.
Событие получено объектом класса EventDemo
Событие получено объектом класса X
Событие получено объектом класса Y
Событие получено объектом класса EventDemo
Событие получено объектом класса Y
В данном примере создаются два дополнительных класса, X и Y, в которых также определяются обработчики событий, совместимые с делегатом MyEventHandler
. Поэтому эти обработчики могут быть также включены в цепочку событий. Обратите внимание на то, что обработчики в классах X и Y не являются статическими. Это означает, что сначала должны быть созданы объекты каждого из этих классов, а затем в цепочку событий должны быть введены обработчики, связанные с их экземплярами. Об отличиях между обработчиками экземпляра и статическими обработчиками речь пойдет в следующем разделе.