События
Событие представляет собой автоматическое уведомление о том, что произошло некоторое действие. События действуют по следующему принципу: объект, проявляющий интерес к событию, регистрирует обработчик этого события. Когда же событие происходит, вызываются все зарегистрированные обработчики этого события. Обработчики событий обычно представлены делегатами.
События являются членами класса и объявляются с помощью ключевого слова event. Чаще всего для этой цели используется следующая форма:
event делегат_события имя_события;
где делегат_события обозначает имя делегата, используемого для поддержки события, а имя_события — конкретный объект объявляемого события.
События основаны на делегатах и предоставляют им механизм публикации/подписки. В каркасе .NET события присутствуют повсюду. В приложениях Windows класс Button поддерживает событие Click. Этот тип события является делегатом. Метод-обработчик, вызываемый с событием Click, должен быть определен с параметрами, заданными в типе делегата.
Как и делегаты, события поддерживают групповую адресацию. Это дает возможность нескольким объектам реагировать на уведомление о событии.
Методы экземпляра и статические методы могут быть использованы в качестве обработчиков событий, но между ними имеется одно существенное отличие. Когда статический метод используется в качестве обработчика, уведомление о событии распространяется на весь класс. А когда в качестве обработчика используется метод экземпляра, то события адресуются конкретным экземплярам объектов. Следовательно, каждый объект определенного класса, которому требуется получить уведомление о событии, должен быть зарегистрирован отдельно. На практике большинство обработчиков событий представляет собой методы экземпляра, хотя это, конечно, зависит от конкретного приложения.
Давайте рассмотрим пример:
using System; namespace ConsoleApplication1 { delegate void UI (); class MyEvent { // Объявляем событие public event UI UserEvent; // Используем метод для запуска события public void OnUserEvent() { UserEvent(); } } class UserInfo { string uiName, uiFamily; int uiAge; public UserInfo(string Name, string Family, int Age) { this.Name = Name; this.Family = Family; this.Age = Age; } public string Name { set { uiName = value; } get { return uiName; } } public string Family { set { uiFamily = value; } get { return uiFamily; } } public int Age { set { uiAge = value; } get { return uiAge; } } // Обработчик события public void UserInfoHandler() { Console.WriteLine("Событие вызвано!\n"); Console.WriteLine("Имя: {0}\nФамилия: {1}\nВозраст: {2}",Name,Family,Age); } } class Program { static void Main() { MyEvent evt = new MyEvent(); UserInfo user1 = new UserInfo(Name: "Alex", Family: "Erohin", Age: 26); // Добавляем обработчик события evt.UserEvent += user1.UserInfoHandler; // Запустим событие evt.OnUserEvent(); Console.ReadLine(); } } }
Как видите, в данном примере создается событие UserEvent, являющееся членом делегата UI. Обработчик данного события определяется в классе UserInfo, и добавляется с помощью синтаксиса +=.
Событие C# в действительности развертывается в два скрытых метода, один из которых имеет префикс add_, а другой — remove_. За этим префиксом следует имя события C#. Например, событие UserEvent превращается в два скрытых метода CIL с именами add_UserEvent() и remove_UserEvent(). Если заглянуть в CIL-код метода add_UserInfoHandler(), можно обнаружить там вызов метода Delegate.Combine().
Комментарии