Какова связь между делегатами и событиями? - PullRequest
6 голосов
/ 28 февраля 2012

Delegate выполняет ту же работу с указателями на функции.Его можно рассматривать как указатели функций управляемого мира.Он просто представляет адрес вызываемой функции вместе с конкретным объектом, метод которого должен быть вызван.

Много раз я читал термин Delegate вместе с термином Event, но не вижуотношения между ними.Является ли Event конкретным типом делегатов?

Ответы [ 5 ]

16 голосов
/ 28 февраля 2012

Краткий ответ: см. мою статью по теме . Более длинный ответ:

События - это шаблон поверх делегатов. Это реализация шаблона издатель / подписчик (он же шаблон наблюдателя ), использующий делегатов в качестве средства представления подписки.

Всякий раз, когда вы видите что-то вроде:

public event EventHandler Foo;

Вместо этого вы должны подумать о двух методах:

public void AddFooHandler(EventHandler handler) { ... }
public void RemoveFooHandler(EventHandler handler) { ... }

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

10 голосов
/ 28 февраля 2012

Ответы пока все очень хорошие, но все они исследуют «механическую» сторону отношений.Я смотрю на это немного по-другому.

Подумайте о кнопке «Пуск» в микроволновой печи.Эта кнопка обеспечивает абстракцию для пользователя микроволновой печи, и кнопка имеет определенные свойства.У него есть размер, у него есть позиция, у него есть текст, у него есть действие при нажатии.

Класс * A Button в программе на C # также предоставляет абстракцию и аналогичным образом имеет определенные свойства.Как и микроволновая кнопка, она имеет размер, позицию, текст и действие при нажатии.

Размер и позиция представлены целыми числами, а текст - строкой.Нельзя сказать, что кнопка микроволновой печи «имеет целые числа, представляющие ее размер и положение, и строку, представляющую ее текст».А для кнопки программного обеспечения тот факт, что она имеет размер, положение и текст, является семантикой кнопки.Тот факт, что размер, положение и текст представлены целыми числами и строками, является фактом о механизмах , из которых построена кнопка, а не фактом о назначении кнопкиили логически какую информацию она представляет миру.

Программная кнопка представляет действие нажатия в качестве события;событие говорит "это вещь, на которую можно нажать".Коллекция делегатов, которая фактически реагирует на нажатие кнопки, является частью механизма .

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

4 голосов
/ 28 февраля 2012

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

3 голосов
/ 28 февраля 2012

A Delegate - это класс, который обычно содержит ссылку на объект в сочетании с указателем на метод, который является либо статическим методом (в этом случае ссылка на объект будет null), либо методом, который гарантированноработа над типом объекта, включенного в делегат.Вызов делегата вызовет указанный метод, при необходимости передав ему содержащийся объект.Делегат также может содержать массив объектов и массив связанных методов, и в этом случае вызов делегата вызовет каждый метод для соответствующего объекта, прерывая процесс в случае возникновения исключения.Все делегаты, даже те, которые имеют только одну пару объект / метод, хранятся как тип, полученный из MulticastDelegate.

. Event - это пара методов, предоставляемых объектом, которые другой код может использовать длялибо запросите, чтобы объект вызвал определенный делегат в некоторых ожидаемых будущих обстоятельствах, либо сообщите объекту, что ему больше не нужно вызывать этот делегат.Большинство объектов примут переданный делегат и добавят его в MulticastDelegate, который затем будет вызывать объект, когда наступит обстоятельства (вызов MulticastDelegate вызовет всех его членов), но объекты свободны для реализации события «add» и «add»удалите «методы доступа», как они считают нужным.

Несколько дополнительных замечаний:

  1. Программа доступа к событиям ничего не говорит ни об обстоятельствах, при которых фактически будут вызываться любые переданные делегаты, никаким образом это произойдет (например, произойдет ли это в каком-либо конкретном потоке).
  2. И компилятор C #, и vb.net автоматически генерируют код для методов «добавления» и «удаления», которые используют `MulticastDelegate` при отсутствии кода, который делает что-то еще.В C # имя MulticastDelegate будет таким же, как и имя события, что может вызвать некоторую путаницу, особенно в старых компиляторах C #, где `eventName + = someDelegate` будет иметь другое значение вне класса, представляющего событие, чемэто было бы внутри.
  3. Делегаты являются неизменными, хотя объекты, на которые они ссылаются, могут не быть.При наличии двух делегатов один может создать новый делегат, который объединяет все пары объект / метод из каждого;Можно также создать делегат, который содержит все пары объект / метод в первой, кроме той, которая соответствует второй, хотя семантика довольно странная, если у второго делегата более одной пары объект / метод.
  4. Следует избегать передачи `MulticastDelegate`, созданного через` Delegate.Combine`, в обработчик события 'add', если есть вероятность того, что любой из составляющих делегатов или других эквивалентных им делегатов также может быть передан, потому чтомногие реализации событий используют сложение и вычитание MulticastDelegate и поэтому страдают от странной семантики «вычитания».

Поскольку пункт № 2 выше, термин «событие» часто используется, особенно в C #, для ссылки на автоматически сгенерированное поле делегата, связанное с событием.В действительности, однако, «событие» не является делегатом - это просто пара методов добавления и удаления (в VB «событие» также включает в себя метод, предназначенный только для использования в классе, для целей «повышения»).«событие (т. е. вызов делегатов, которые ранее были переданы методу add); это просто синтаксический сахар, позволяющий использовать синтаксис RaiseEvent EventName(params) в качестве альтернативы непосредственному вызову соответствующего метода).

3 голосов
/ 28 февраля 2012

Краткий ответ .

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

Длинный ответ

Событие - это сообщение, отправленное объектом для оповещения о наступлении действия. Действие может быть вызвано взаимодействием с пользователем, например щелчком мыши, или оно может быть вызвано некоторой другой программной логикой. Объект, который вызывает событие, называется отправителем события. Объект, который захватывает событие и отвечает на него, называется получателем события.

В связи с событием класс отправителя события не знает, какой объект или метод получит (обработает) события, которые он вызывает. Требуется посредник (или механизм, похожий на указатель) между источником и получателем. .NET Framework определяет специальный тип (Delegate), который обеспечивает функциональность указателя функции.

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

подробнее на:

http://msdn.microsoft.com/en-us/library/17sde2xt(v=vs.100).aspx

...