Руководство по программированию на C#. Подписка и отмена подписки на события

Необходимость подписки на событие, опубликованное другим классом, может возникнуть, когда требуется написать пользовательский код, вызываемый при инициировании такого события. Например, можно подписаться на событие кнопки click, чтобы приложение выполняло некоторое действие при нажатии пользователем кнопки.

Подписка на события в интегрированной среде разработки Visual Studio

  1. Если окно Свойства закрыто, в представлении Конструктор щелкните правой кнопкой мыши форму или элемент управления, для которого требуется создать обработчик событий, и выберите пункт Свойства.

  2. Вверху окна Свойства щелкните значок События.

  3. Дважды щелкните событие, которое требуется создать, например событие 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);  
    

Подписка на события программными средствами

  1. Определите метод обработчика событий, сигнатура которого соответствует сигнатуре делегата для события. Например, если событие основано на типе делегата EventHandler, то следующий код представляет заглушку метода:

    void HandleCustomEvent(object sender, CustomEventArgs a)  
    {  
       // Do something useful here.  
    }  
    
  2. Чтобы присоединить обработчик событий к событию, используйте оператор присваивания сложения (+=). В приведенном ниже примере предположим, что объект с именем publisher имеет событие с именем RaiseCustomEvent. Обратите внимание на то, что классу подписчика требуется ссылка на класс издателя, чтобы подписаться на его события.

    publisher.RaiseCustomEvent += HandleCustomEvent;  
    

    Чтобы указать обработчик событий, можно также воспользоваться лямбда-выражением:

    public Form1()  
    {  
        InitializeComponent();  
        this.Click += (s,e) =>
            {
                MessageBox.Show(((MouseEventArgs)e).Location.ToString());
            };
    }  
    

Подписка на события с помощью анонимной функции

Если вам не нужно будет позже отменять подписку на событие, можно использовать оператор присваивания сложения (+=) для привязки анонимной функции как обработчика событий. В следующем примере предположим, что объект с именем publisher имеет событие с именем RaiseCustomEvent и что класс CustomEventArgs также был определен и содержит некие относящиеся к событию сведения. Обратите внимание на то, что классу подписчика требуется ссылка на publisher, чтобы подписаться на его события.

publisher.RaiseCustomEvent += (object o, CustomEventArgs e) =>
{  
  string s = o.ToString() + " " + e.ToString();  
  Console.WriteLine(s);  
};  

Отменить подписку на событие не так просто, если для подписки использовалась анонимная функция. Чтобы отменить подписку в этом случае, в коде, где была выполнена подписка на событие, сохраните анонимную функцию в переменной делегата, а затем добавьте делегат к событию. Мы рекомендуем не использовать анонимные функции для подписки на события, если в будущем вам нужно будет отменить подписку. Дополнительные сведения об анонимных функциях см. в статье Лямбда-выражения.

Отмена подписки

Чтобы предотвратить вызов обработчика событий при инициировании события, подписку на событие необходимо отменить. Во избежание утечки ресурсов отменять подписку на события следует до удаления объекта подписчика. До тех пор пока подписка на событие не отменена, делегат многоадресной рассылки, лежащий в основе события в публикующем объекте, будет ссылаться на делегат, инкапсулирующий обработчик событий подписчика. Если ссылка присутствует в публикующем объекте, объект подписчика не будет удален при сборке мусора.

Отмена подписки на событие

  • Чтобы отменить подписку на событие, воспользуйтесь оператором присваивания вычитания (-=).

    publisher.RaiseCustomEvent -= HandleCustomEvent;  
    

    Если подписка на событие отменена для всех подписчиков, экземпляр события в классе издателя получает значение null.

См. также