Событие | Event

Событие - член типа, который использует делегат, для того чтобы уведомить всех подписчиков о проишествии события.

События позволяют классу или объекту уведомлять другие классы или объекты овозникновении каких-либо ситуаций.

  • Класс, отправляющий (или вызывающий) событие, называется издателем.

  • Классы, принимающие (или обрабатывающие) событие, называются подписчиками.

События сами по себе могут быть объявлены двумя способами. Первый способ — с явной (explicit) реализацией методов add и remove; этот способ очень похож на свойства с явно объявленными геттерами (get) и сеттерами (set), но с ключевым словом event. Ниже представлен пример:

public event EventHandler MyEvent
{
    add
    {
        myEvent += value;
    }
    remove
    {
        myEvent -= value;
    }
}

В реализации по умолчанию для event'а заводится скрытое поле типа делегата, а add/remove добавляют или убирают из него методы (под lock'ом). (Чтобы немного запутать картину, это скрытое поле доступно по тому же имени, что иevent.) Функцииadd/remove, составляющиеevent,вызываются соответственно как+=и-=. Никаких операций+/-, разумеется, нету.

Отличия event'а в классе от публичного поля типа делегата.

Рассмотрим случай, когда event реализован «по умолчанию», то есть, с неявным делегатным полем. Отличие состоит в том, что:

1) Для делегатного поля - у вас полный доступ к нему. Снаружи класса заменить его на свой или присвоить емуnull, вы можете его вызвать, можете его скопировать себе в переменную. У вас есть полный доступ, как и к любому публичному полю. (Это, разумеется, вопиющим образом нарушает инкапсуляцию.)

Для event'а, вы можете лишь написатьinstance.Event += handlerиinstance.Event -= handler, что отображается на функцииaddиremove, которые в свою очередь снова-таки вызывают+=и-=для автоматически реализованного делегата. Никакого другого доступа у вас нету.

Для случая, когда event реализуется не «по умолчанию», общего нет практически ничего. Методыaddиremoveмогут делать всё, что угодно:

int subscriberCount = 0;
public event EventHandler MyEvent
{
    add
    {
        subscriberCount++;
    }
    remove
    {
        subscriberCount--;
    }
}

Программист может завести делегат самостоятельно и «складывать» туда подписанные обработчики, но это в принципе его добрая воля. С другой стороны, всё же рекомендуется не ломать ожидаемую клиентами семантику класса, и использовать event по назначению.

Запрещено вызывать событие извне класса.

На событие можно подписать анонимный метод, но без возможности отписки. (подробнее на курсе Professional)

События сами по себе могут быть объявлены двумя способами. Первый способ — с явной (explicit) реализацией методов add и remove:

public event EventHandler MyEvent
{
    add
    {

    }

    remove
    {

    }
}

Field-like события

Простой способ объявления переменной делегата и события в один и тот же момент. Этот способ называется «field-like событием» (field-like event) и объявляется очень просто — так же, как и «длинная» форма объявления события (приведённая выше), но без «тела» с методами add и remove.

public event EventHandler MyEvent;

Эта форма создает переменную делегата и событие с одинаковым типом. Доступ к событию определяется в объявлении события с помощью модификатора доступа, но переменная делегата всегда приватна. Событие из примера выше эквивалентно следующему коду:



results for ""

    No results matching ""