На собеседованиях собеседователи любят задавать всякие каверзные вопросы. Одним из любимых вопросов на понимание .net платформы является вопрос про события и делегаты. В лучшем случае спрашивают отличия, в худшем могут задать такой вопрос на засыпку.
Дан код:
1. Что будет с программой, если класс A видоизменить так: убрать ключевое слово
2. Что будет с программой, если вообще во всем коде убрать ключевые слова
Неподготовленных вопросы вводят в жуткий когнитивный диссонанс, как только они их осознают. Здесь главное удержаться от негодующего вопля и вспомнить синтаксические отличия применимости событий от делегатов:
0. Событие — это тот же самый делегат, который наделяется некоторыми свойствами через слово
1. И событие и делегат можно объявить полем класса, но в отличие от делегата, событие не может быть локальной переменной метода (особо не роляет, но помнить стоит)
2. Событие нельзя запустить вне класса, в котором оно было объявлено (это самое важное отличие!!!)
3. Интерфейс не может содержать поля.
4. Событие всегда объявляется как «поле», а не свойство (
Это, пожалуй, единственные отличия события от делегата (я не берусь рассматривать семантическую разницу). Ну, или я что-то забыл, но вы мне сейчас напомните:)
Итак, если у нас есть интерфейс, в котором объявлено событие, и мы убираем ключевое слово
Поэтому ответы на вопросы будут такие:
1. Ничего не изменится
2. Ничего не изменится, если только в программе нет объявленных в интерфейсах событий.
Да, и еще вот что удивительно — при ответе на вопрос некоторые начинают рассуждать, что событие — это
П.С. Да, я знаю, что
Дан код:
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:)