Какая связь между делегатами и событиями?

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

много раз я читал термин Delegate наряду с терминомEvent но я не вижу связи между ними. Это Event определенный тип делегатов?

5 ответов


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

события шаблон сверху делегатов. Их реализация издатель/подписчик шаблон (он же шаблон Observer), используя делегатов в качестве средства представления подписки.

когда вы видите что-то вроде:

public event EventHandler Foo;

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

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

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


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

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

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

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

программная кнопка представляет действие нажатия как событие; событие говорит:"это то, что можно щелкнуть". Сбор делегатов, которые на самом деле respondes при нажатии кнопки будет часть .

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


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


короткий ответ:.

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

Ответ

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

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

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

дополнительная информация по адресу:

http://msdn.microsoft.com/en-us/library/17sde2xt (v=против 100).aspx


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

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

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

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

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