Pull to refresh

Коварный вопрос по Event \ Delegate

Reading time2 min
Views64K
На собеседованиях собеседователи любят задавать всякие каверзные вопросы. Одним из любимых вопросов на понимание .net платформы является вопрос про события и делегаты. В лучшем случае спрашивают отличия, в худшем могут задать такой вопрос на засыпку.



Дан код:

public class A
{
  public void OnDoWork()
  {
    if ( DoWork != null )
      DoWork(this, EventArgs.Empty);
  }

  public event EventHandler DoWork;
}


* This source code was highlighted with Source Code Highlighter.


1. Что будет с программой, если класс A видоизменить так: убрать ключевое слово event?
2. Что будет с программой, если вообще во всем коде убрать ключевые слова event?

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

0. Событие — это тот же самый делегат, который наделяется некоторыми свойствами через слово event.
1. И событие и делегат можно объявить полем класса, но в отличие от делегата, событие не может быть локальной переменной метода (особо не роляет, но помнить стоит)
2. Событие нельзя запустить вне класса, в котором оно было объявлено (это самое важное отличие!!!)
3. Интерфейс не может содержать поля.
4. Событие всегда объявляется как «поле», а не свойство (add-remove не в счет).

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

Итак, если у нас есть интерфейс, в котором объявлено событие, и мы убираем ключевое слово event, то у нас возникает ошибка компилятора — дескать, интерфейс не может содержать поля (а именно полем-делегатом стало бывшее событие). Но если событие объявлено как поле класса, то с точки зрения компилятора будет совершенно корректно убрать ключевое слово.

Поэтому ответы на вопросы будут такие:
1. Ничего не изменится
2. Ничего не изменится, если только в программе нет объявленных в интерфейсах событий.

Да, и еще вот что удивительно — при ответе на вопрос некоторые начинают рассуждать, что событие — это MulticastDelegate, а вот Delegate может содержать ссылку только на один метод. В общем, это совершенно жуткая ересь, но тем не менее несколько разных людей мне таким образом пытались дать ответ на эти два вопроса. Откуда пошел этот миф, неизвестно. Если есть желание посмотреть, в чем же отличие MulticastDelegate от Delegate — можно сбегать поглядеть статью мегаавторитета Брэда Абрамса — и убедиться, что различий между этим классами, кроме названия, нет.

П.С. Да, я знаю, что OnDoWork() не thread safe:)
Tags:
Hubs:
+18
Comments91

Articles

Change theme settings