Практическое руководство. Подписка и отмена подписки на события (Руководство по программированию в C#)
Обновлен: Ноябрь 2007
Необходимость подписки на событие, опубликованное другим классом, может возникнуть когда требуется написать пользовательский код, вызываемый при инициировании такого события. Например, можно подписаться на событие кнопки click, чтобы приложение выполняло некоторое действие при нажатии пользователем на кнопку.
Подписка на события в среде IDE Visual Studio
Если окно Свойства закрыто, в представлении Конструктор щелкните правой кнопкой мыши форму или элемент управления, для которого требуется создать обработчик событий, и выберите пункт Свойства.
Вверху окна Свойства щелкните значок События.
Дважды щелкните событие, которое требуется создать, например событие Load.
Visual C# создаст пустой метод обработчика событий и добавит его в код. Код можно также добавить вручную в представлении Код. Например, следующие строки кода объявляют метод обработчика событий, который будет выполнен при инициировании классом Form события Load.
private void Form1_Load(object sender, System.EventArgs e) { // Add your form load event handling code here. }
Строка кода, то есть которая требуется для подписки на событие, также создается автоматически в методе InitializeComponent в файле Form1.Designer.cs проекта. Она имеет следующий вид.
this.Load += new System.EventHandler(this.Form1_Load);
Подписка на события программными средствами
Определите метод обработчика событий, подпись которого соответствует подписи делегата для события. Например, если событие основано на типе делегата EventHandler, то следующий код представляет заглушку метода:
void HandleCustomEvent(object sender, CustomEventArgs a) { // Do something useful here. }
Чтобы присоединить обработчик событий к событию, используйте оператор назначения сложения (+=). В следующем примере предположим, что объект с именем publisher имеет событие с именем RaiseCustomEvent. Обратите внимание, что для класса подписчика требуется ссылка на класс издателя, чтобы подписаться на его события.
publisher.RaiseCustomEvent += HandleCustomEvent;
Обратите внимание, что предыдущий синтаксис является нововведением в языке C# версии 2.0. Он в точности соответствует синтаксису C# 1.0, в котором при помощи ключевого слова new должен быть явно создан инкапсулирующий делегат.
publisher.RaiseCustomEvent += new CustomEventHandler(HandleCustomEvent);
Для добавления обработчика событий можно также использовать лямбда-выражение.
public Form1() { InitializeComponent(); // Use a lambda expression to define an event handler. this.Click += (s,e) => { MessageBox.Show( ((MouseEventArgs)e).Location.ToString());}; }
Дополнительные сведения см. в разделе Практическое руководство. Использование лямбда-выражений вне LINQ (Руководство по программированию на C#).
Подписка на события при помощи анонимного метода
Если не нужно будет позже отменять подписку на событие, можно использовать оператор назначения сложения (+=) для прикрепления к событию анонимного метода. В следующем примере предположим, что объект с именем publisher имеет событие с именем RaiseCustomEvent, и что класс CustomEventArgs также был определен и содержит некие относящиеся к событию сведения. Обратите внимание, что для класса подписчика требуется ссылка на publisher, чтобы подписаться на его события.
publisher.RaiseCustomEvent += delegate(object o, CustomEventArgs e) { string s = o.ToString() + " " + e.ToString(); Console.WriteLine(s); };
Важно отметить, что отменить подписку на событие не так просто, если для подписки на него использовалась анонимная функция. Чтобы отменить подписку в этом случае, необходимо вернуться к коду, в котором была выполнена подписка на событие, сохранить анонимный метод в переменной делегата, а затем добавить делегат к событию. Как правило, мы рекомендуем не использовать анонимных функций для подписки на события, если предполагается, что в будущем будет нужно отменять подписку на событие. Дополнительные сведения об анонимных функциях см. в разделе Анонимные функции (Руководство по программированию в C#).
Отмена подписки
Чтобы предотвратить вызов обработчика событий при инициировании события, подписку на событие необходимо отменить. Во избежание утечки ресурсов отменять подписку на события следует до удаления объекта подписчика. До тех пор, пока подписка на событие не отменена, делегат многоадресной рассылки, лежащий в основе события в публикующем объекте, будет ссылаться на делегат, инкапсулирующий обработчик событий подписчика. Если ссылка присутствует в публикующем объекте, объект подписчика не будет удален при сборке мусора.
Отмена подписки на событие
Чтобы отменить подписку на событие, воспользуйтесь оператором назначения вычитания (-=).
publisher.RaiseCustomEvent -= HandleCustomEvent;
Если подписка на событие отменена для всех подписчиков, экземпляр события в классе издателя получает значение null.
См. также
Задачи
Ссылки
События (Руководство по программированию в C#)