События

43

Событие представляет собой автоматическое уведомление о том, что произошло некоторое действие. События действуют по следующему принципу: объект, проявляющий интерес к событию, регистрирует обработчик этого события. Когда же событие происходит, вызываются все зарегистрированные обработчики этого события. Обработчики событий обычно представлены делегатами.

События являются членами класса и объявляются с помощью ключевого слова 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();
        }
    }
}
Использование событий C#

Как видите, в данном примере создается событие UserEvent, являющееся членом делегата UI. Обработчик данного события определяется в классе UserInfo, и добавляется с помощью синтаксиса +=.

Событие C# в действительности развертывается в два скрытых метода, один из которых имеет префикс add_, а другой — remove_. За этим префиксом следует имя события C#. Например, событие UserEvent превращается в два скрытых метода CIL с именами add_UserEvent() и remove_UserEvent(). Если заглянуть в CIL-код метода add_UserInfoHandler(), можно обнаружить там вызов метода Delegate.Combine().

Пройди тесты
Лучший чат для C# программистов