Главная цель событий в С#

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

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

Так есть ли кто-нибудь, кто может объяснить смелую часть?

Спасибо заранее.

Ответ 1

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

Предположим, что Button.Click были публичным полем или свойством, а не событием. Одна часть кода могла затем подписаться на событие, а другая могла бы написать:

// Invalid with events, valid with properties
button.Click = null;

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

// Invalid with events, valid with properties
button.Click(this, EventArgs.Empty);

хотя кнопка не была нажата. Это явно является нарушением инкапсуляции. Единственная причина, по которой выставлять Click для другого кода, - это позволить им регистрировать интерес к нажатиям кнопок и позже регистрировать незаинтересованность - и это именно те возможности, которые предоставляют события.

Подумайте о событиях как синтаксическом сахаре вокруг двух методов. Например, если у нас не было событий, то Button, вероятно, имел бы:

public void AddClickHandler(EventHandler handler)
public void RemoveClickHandler(EventHandler handler)

Нарушение инкапсуляции исчезает, но вы теряете часть удобства - и каждый должен написать свои собственные методы, подобные этому. События упрощают этот шаблон, в основном.

Ответ 2

Событие может быть вызвано только классом, определяющим его, тогда как делегат может быть вызван у кого-то, у кого есть доступ к нему. Вот что я считаю жирным шрифтом.

Кроме того, событие может быть определено в интерфейсе, тогда как делегат не может (поскольку вы объявляете делегат как поле).

Я рекомендую дать ссылку эту ссылку, так как она объясняет это довольно красиво и имеет еще несколько примеров, кроме вышеупомянутых.

Ответ 3

Вы можете установить делегат в NULL, который заставляет его "забывать" каждую функцию, подписанную на него.

Ответ 4

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