События
43C# --- Руководство по C# --- События
Событие представляет собой автоматическое уведомление о том, что произошло некоторое действие. События действуют по следующему принципу: объект, проявляющий интерес к событию, регистрирует обработчик этого события. Когда же событие происходит, вызываются все зарегистрированные обработчики этого события. Обработчики событий обычно представлены делегатами.
События являются членами класса и объявляются с помощью ключевого слова 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().