Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Разработчики, которые являются новыми для платформы .NET, часто борются при выборе между проектом на основе delegates
и дизайна на основе events
. Выбор делегатов или событий часто затруднен, так как два языковых компонента похожи. События даже создаются с помощью поддержки языка для делегатов. Объявление обработчика событий объявляет тип делегата.
Оба предлагают сценарий последней привязки: они позволяют использовать сценарии, в которых компонент взаимодействует, вызывая метод, известный только во время выполнения. Они поддерживают как одиночные, так и множественные методы подписки. Эти термины могут называться поддержкой одноадресной рассылки и многоадресной рассылки. Они оба поддерживают аналогичный синтаксис для добавления и удаления обработчиков. Наконец, вызов события и вызов делегата используют точно тот же синтаксис вызова метода. Они даже поддерживают один и тот же синтаксис метода Invoke()
для использования с оператором ?.
.
При всех этих сходствах легко запутаться в том, когда какое из них использовать.
Прослушивание событий является необязательным
Самым важным соображением при выборе языковой функции является необходимость наличия подключенного подписчика. Если код должен вызывать код, предоставленный подписчиком, следует использовать дизайн на основе делегатов, когда необходимо реализовать обратный вызов. Если код может завершить всю работу без вызова подписчиков, следует использовать дизайн на основе событий.
Рассмотрим примеры, созданные в этом разделе. Код, созданный с помощью List.Sort()
, должен быть предоставлен функцию сравнения для правильной сортировки элементов. Запросы LINQ должны предоставляться делегатам, чтобы определить, какие элементы следует возвращать. Оба использовали дизайн, созданный с помощью делегатов.
Рассмотрим событие Progress
. Он сообщает о ходе выполнения задачи. Задача продолжается независимо от того, есть ли слушатели.
FileSearcher
является еще одним примером. Он всё равно будет искать и находить все файлы, которые были запрошены, даже без подключённых подписчиков событий. Элементы управления UX по-прежнему работают правильно, даже если подписчики не прослушивают события. Они оба используют дизайны на основе событий.
Возвращаемые значения требуют делегатов
Другим фактором является прототип метода, который требуется для метода делегата. Как вы видели, делегаты, используемые для событий, имеют тип возвращаемых данных void. Существуют идиомы для создания обработчиков событий, которые передают информацию обратно в источники событий путем изменения свойств объекта аргумента события. Хотя эти идиомы работают, они не так естественны, как возврат значения из метода.
Обратите внимание, что эти два эвристика часто могут присутствовать: если метод делегата возвращает значение, он влияет на алгоритм каким-то образом.
События имеют приватный вызов
Классы, кроме того класса, в котором находится событие, могут только добавлять и удалять прослушиватели событий; только класс, содержащий событие, может его вызвать. События обычно являются элементами общедоступного класса. В отличие от этого, делегаты часто передаются в качестве параметров и сохраняются как закрытые члены класса, если они вообще хранятся.
Слушатели событий часто имеют более длительный срок существования
Более длительное время существования прослушивателей событий является немного слабым обоснованием. Однако вам может показаться, что разработки на основе событий более естественны, когда источник событий генерирует события в течение длительного периода времени. Примеры проектирования на основе событий для элементов управления пользовательским интерфейсом можно увидеть во многих системах. После подписки на событие источник событий может вызывать события в течение всего времени существования программы. (Вы можете отменить подписку на события, если они больше не нужны.)
В отличие от многих проектов, основанных на делегатах, где делегат используется как аргумент метода, но перестает использоваться после его завершения.
Тщательно оцените
Приведенные выше рекомендации не являются сложными и быстрыми правилами. Вместо этого они представляют рекомендации, которые помогут вам решить, какой выбор лучше всего подходит для конкретного использования. Поскольку они похожи, вы можете даже создать прототипы для обоих и подумать, с каким из них будет более естественно работать. Оба они хорошо обрабатывают сценарии позднего связывания. Используйте тот, который лучше всего передает вашу дизайнерскую идею.