На собеседованиях любят задавать всякие каверзные вопросы. Одним из любимых вопросов на понимание .net платформы является вопрос про события и делегаты. В лучшем случае спрашивают отличия, в худшем могут задать такой вопрос на засыпку.
Дан код:
1 2 3 4 5 6 7 8 9 10 | public class A { public void OnDoWork() { if ( DoWork != null ) DoWork(this, EventArgs.Empty); } public event EventHandler DoWork; } |
- Что будет с программой, если класс A видоизменить так: убрать ключевое слово event?
- Что будет с программой, если вообще во всем коде убрать ключевые слова event?
Неподготовленных вопросы вводят в жуткий когнитивный диссонанс, как только они их осознают. Здесь главное удержаться от негодующего вопля и вспомнить синтаксические отличия применимости событий от делегатов:
- Событие — это тот же самый делегат, который наделяется некоторыми свойствами через слово event.
- И событие и делегат можно объявить полем класса, но в отличие от делегата, событие не может быть локальной переменной метода (особо не роляет, но помнить стоит)
- Событие нельзя запустить вне класса, в котором оно было объявлено (это самое важное отличие!!!)
- Интерфейс не может содержать поля.
- Событие всегда объявляется как «поле», а не свойство (add-remove не в счет).
Это, пожалуй, единственные отличия события от делегата (я не берусь рассматривать семантическую разницу). Ну, или я что-то забыл, но вы мне сейчас напомните:)
Итак, если у нас есть интерфейс, в котором объявлено событие, и мы убираем ключевое слово event, то у нас возникает ошибка компилятора — дескать, интерфейс не может содержать поля (а именно полем-делегатом стало бывшее событие). Но если событие объявлено как поле класса, то с точки зрения компилятора будет совершенно корректно убрать ключевое слово.
Поэтому ответы на вопросы будут такие:
- Ничего не изменится
- Ничего не изменится, если только в программе нет объявленных в интерфейсах событий.
Да, и еще вот что удивительно — при ответе на вопрос некоторые начинают рассуждать, что событие — это MulticastDelegate, а вот Delegate может содержать ссылку только на один метод. В общем, это совершенно жуткая ересь, но тем не менее несколько разных людей мне таким образом пытались дать ответ на эти два вопроса. Откуда пошел этот миф, неизвестно. Если есть желание посмотреть, в чем же отличие MulticastDelegate от Delegate — можно сбегать поглядеть статью мегаавторитета Брэда Абрамса — и убедиться, что различий между этим классами, кроме названия, нет.
П.С. Да, я знаю, что OnDoWork() не thread safe:)





