Зачем нам нужно ключевое слово "event" при определении событий?

Я не понимаю, зачем нам нужно ключевое слово event при определении событий, когда мы можем сделать то же самое, не используя ключевое слово "event", просто используя делегаты.

например.

public delegate void CustomEventHandler(int a, string b);
public event CustomEventHandler customEvent;
customEvent += new CustomEventHandler(customEventHandler);
customEvent(1,"a"); // Raising the event

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

Ответ 1

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

Событие в корне похоже на свойство - это пара методов add/remove (вместо get/set свойства). Когда вы объявляете полевое событие (т.е. Тот, где вы сами не указываете бит добавления/удаления), создается публичное событие и частное поле поддержки. Это позволяет вам публиковать мероприятие конфиденциально, но разрешить публичную подписку. С открытым полем делегирования каждый может удалить обработчики событий других людей, сам инициировать событие и т.д. - это катастрофа инкапсуляции.

Подробнее о событиях (и делегатах) читайте в статье в этом разделе. (В какой-то момент мне нужно обновить это для С# 4, что очень мало меняет события, подобные полям. Суть этого все равно правильная.)

Ответ 2

Другие ответы прекрасны; Я просто хотел бы добавить что-то еще, о чем подумать.

Ваш вопрос: "Почему нам нужны события, когда у нас есть поля типа делегата?" Я бы затронул этот вопрос: зачем вам нужны методы, свойства, события, конструкторы экземпляров или финализаторы, если у вас есть поля типа делегата? Зачем вам нужно что-то другое, кроме полей, содержащих значения и делегаты в типе? Почему бы просто не сказать

class C
{
    private int z;
    public readonly Func<int, int> M = (int x)=>{ return x+z; }
    // ... and so on
}

?

Вам не нужны методы, свойства или события. Мы даем вам эту информацию, потому что шаблоны методов, свойств и дизайна событий важны и полезны и заслуживают стандартного, документированного и четкого способа их реализации на языке.

Ответ 3

Ключевое слово события делает 3 разных вещи:

  • Вы можете определить событие в интерфейсе, даже если вы не можете определять обычные поля в интерфейсах.
  • Он изменяет видимость операторов = и () (назначение и вызов) на private, так что только содержащий класс может вызвать событие или переопределить все методы, содержащиеся в нем. Операторы -= и += все еще могут быть вызваны в событии вне класса, определяющего его (они получают модификатор доступа, который вы написали рядом с событием).
  • Вы также можете переопределить поведение -= и += для событий.

Ответ 4

Отчасти это необходимо, потому что если вы опускаете ключевое слово event, оно прерывает инкапсуляцию. Если это просто публичный делегат многоадресной передачи, любой может вызвать его, установить для него значение null или вмешательство в него. Если класс с именем MailNotifier существует и имеет событие с именем MailReceived, для других типов нет смысла запускать это событие через вызов mailNotifier.MailReceived();

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

Если вы хотите, чтобы ваше приглашение на мероприятие было закрыто, вам нечего делать, например:

public class MyClassWithNonFieldLikeEvent
{
   private CustomEventHandler m_delegate;

   public void Subscribe(CustomEventHandler handler) 
   {
      m_delegate += handler;        
   }

   public void Unsubscribe(CustomEventHandler handler)
   {          
      m_delegate -= handler;
   }

   private void DoSomethingThatRaisesEvent()
   {
      m_delegate.Invoke(...);
   }       
}

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

Ответ 5

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

Подробнее см. этот пост в блоге.