C# - Win Forms - Цикл потока событий

Я читал рефкарту Джона Скита на C#. Он постановил:

"События тесно связаны с делегатами, но это не одно и то же".

Поэтому, насколько я понимаю, когда возникают события, обработчики (делегаты) выполняют код.

У меня есть следующие сомнения:

(1) Когда мы объявляем событие, оно будет зарегистрировано в каком-либо "РЕГИСТРАЦИЯХ"? или "Системные реестры"?

(2) Старый стиль VB 6.0 обрабатывает событие без делегатов, так почему мы не можем написать событие без делегатов?

Как продвигается поток для Win Forms: Если я нажму кнопку, она напечатает привет (следующий пример).

button_click( sender,some event args  )
{
    print();
} 

void print( )
{
    console.WriteLine ("Hello");
}

Как этот поток событий внутренне связан и обрабатывается? (Что внутри происходит в CLR?)

(3) Какова логика позади события, которое препятствует тому, чтобы событие возвратило значение?

Спасибо всем, что потратили свое золотое время.

4 ответа

Решение

delegate это определение типа. Он определяет сигнатуру, что метод должен быть совместимым.

event это свойство класса элемента, основанного на типе делегата. Он обеспечивает инкапсуляцию, единственные открытые действия - добавить (+=) или удалить (-=) обработчик.

(1) Нет, событие нигде не зарегистрировано. Но это место, где регистрируются методы обработки.

(2) Я не знаю, как работает VB6, но в.NET все события основаны на делегатах.

(2b) При нажатии кнопки происходит то, что код кнопки проверяет, не является ли событие нулевым, и затем вызывает событие (как метод). Событие перебирает свой список вызовов и вызывает все зарегистрированные обработчики.

есть еще кое-что: ButtonClick создается самой Button, когда она обрабатывает и обрабатывает события мыши и / или клавиатуры. Эти события приходят из MessageLoop (Application.Run). Но на уровне CLR это просто означает, что MessageLoop вызывает метод (Control.Perform(..)) для Button.

(3) Вы можете написать делегат и / или событие, которое просто отлично возвращает значение. Но подумайте, что это значит, когда есть несколько обработчиков. Подпись void handler(object sender, Eventargs e) является (сильной) рекомендацией.

События реализуются с использованием делегатов:

Этот код:

public event EventHandler<YourEventArgs> YourEvent;

Будет скомпилировано во что-то вроде этого:

// a private field
private EventHandler<YourEventArgs> YourEvent = null;

// public add_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_YourEvent(EventHandler<YourEventArgs> value)
{
    YourEvent = (EventHandler<YourEventArgs>)
    Delegate.Combine(YourEvent, value);
}

// public remove_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_YourEvent(EventHandler<YourEventArgs> value)
{
    YourEvent = (EventHandler<YourEventArgs>)
    Delegate.Remove(YourEvent, value);
}

Поэтому, когда вы объявляете событие, вы фактически объявляете эти две функции. Как видите, эти функции инкапсулируют доступ к полю делегата. Вот почему вы не можете назначить значение делегата на событие, только подписаться или отписаться.

Этот код объясняет, почему события могут быть объявлены с использованием следующего синтаксиса:

public event MyDelegate MyEvent
{
    add
    {
        ...
    }

    remove
    {
        ...
    }
}

1) Событие не будет зарегистрировано ни в каком реестре. Память для события (для частного поля делегата) будет выделена в куче, поскольку делегаты являются ссылочными типами.

2) События строятся поверх делегатов, поэтому вы не можете использовать их без делегатов.

3) На третий вопрос уже ответил Хенк Холтерман (+1) и другие люди.

Надеюсь это поможет.

  1. Я не знаю об этом... но моя первая мысль - о куче, так как именно там живет большинство объектов, а события являются частью объекта... но я рискну догадаться об этом....

  2. Они на самом деле делают, но за кулисами для вас. Это особенность VB.

  3. Они могут иметь более одного делегата / слушателя, и порядок запуска слушателей не гарантируется. Соглашение заключается в использовании объекта eventarg для возврата информации обработчику. Почему у событий нет типов возврата в.NET? входит в немного лучшее описание по этому вопросу.

1) Нет, обработчики событий будут просто зарегистрированы в Event (который содержит список обработчиков).

2) Я не особо разбираюсь в VB6, но я вполне уверен, что у него была похожая механика, поскольку, по сути, Delegate - это просто указатель на метод строгого типа.

В вашем примере Button.Click событие содержит ссылку на делегата button_click( sender,some event args) который он призывает к событию, вызванному. Он не содержит ссылки на печать, просто ссылку на метод, который должен вызвать.

3) Поскольку для одного события может быть несколько обработчиков (или их вообще нет), возвращаемое значение часто может быть нелогичным. Таким образом, большинство обработчиков событий имеют void вернуть. При этом вы можете создавать собственные события, которые могут иметь любую подпись. void (object sender, EventArgs e) подпись является базовой подписью для большинства, если не для всех событий Microsoft.

Другие вопросы по тегам