2010-06-12 5 views
76

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

например.

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

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

+0

ok Если вы не используете ключевое слово event, кто может получить доступ к этому событию с использованием объекта класса, установите его в NULL как objClass.SelectedIndexChanged = null. это приведет к сбою вашего базового кода. ключевое слово event принуждает пользователя назначать что-то подобное делегату, используя + =. –

ответ

92

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

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

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

+4

Это в тысячу раз лучше, чем официальное однострочное объяснение MSDN: «Ключевое слово события используется для объявления события в классе издателя». – cowlinator

5

Отчасти это необходимо, потому что, если вы опускаете ключевое слово 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(...); 
    }  
} 

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

+0

Было бы труднее использовать такие вещи, как дизайнеры ... вы в основном полагаетесь на соглашения об именах для методов, вместо того, чтобы публиковать метаданные, говорящие «это событие». –

3

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

Для получения дополнительной информации см. this blog post.

+2

Вы не должны сравнивать события и * делегаты * - сравнивать события и * публичные поля с типом делегирования *. И нет, фреймворк * не требует, чтобы события имели такую ​​подпись. Вы можете создать событие любого типа делегата, который вам нравится. –

+0

Большое спасибо. Из книг было непонятно. – teenup

+0

спасибо jon, исправлено. – Femaref

16

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

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

Проверьте http://pastebin.com/TMpib9ux. Я привел несколько примеров. :) –

+0

очень ясно ваше объяснение – lucasasecas

16

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

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

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

?

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

+1

Ничего себе! Это напоминает, почему я люблю C#! Из всех языков, с которыми я работал, он имеет правильный баланс компактности, гибкости и удобочитаемой семантики. Единственным сравнимым языком является Object Pascal. –

+0

Это не то, о чем он просил. Он задал разумный вопрос: зачем нам ключевое слово event, т. Е. Делает ли оно что-либо ... какая разница, когда это было бы полезно. И ваш вопрос приравнивает его к тому, почему нам нужны методы и свойства, поэтому зачем нам нужны объекты, почему ООП, почему методы так почему-то процедуры, а почему не просто императивное программирование .. И вы говорите «потому что это полезно». Ну, очевидно. Он спрашивал, в частности, не почему методы полезны, а не почему ООП полезен. И просто сказать, что ключевое слово event полезно, не сокращает его, не говоря о том, почему. – barlop

+0

@barlop: Не стесняйтесь писать ответ, который вам больше нравится в этом семилетнем вопросе, если вам это не нравится. Таким образом, весь сайт становится лучше. –

Смежные вопросы