Почему события в C # должны принимать (отправитель, EventArgs)? - PullRequest
37 голосов
/ 19 сентября 2008

Известно, что вы должны объявлять события, которые принимают в качестве параметров (object sender, EventArgs args). Почему?

Ответы [ 10 ]

22 голосов
/ 19 сентября 2008

Это позволяет разработчику-потребителю написать один обработчик событий для нескольких событий независимо от отправителя или события.

Редактировать: Зачем вам нужен другой шаблон? Вы можете унаследовать EventArgs для предоставления любого объема данных, и изменение шаблона только приведет к путанице и разочарованию любого разработчика, вынужденного использовать этот новый шаблон.

11 голосов
/ 19 сентября 2008

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

6 голосов
/ 19 сентября 2008

Потому что это хороший шаблон для любого механизма обратного вызова, независимо от языка. Вы хотите знать, кто отправил событие (отправитель) и данные, которые имеют отношение к событию (EventArgs).

4 голосов
/ 20 сентября 2008

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

В противном случае последовательность и принцип наименьшего удивления оправдывают использование EventArgs для передачи данных.

Что касается отправителя, то в некоторых (но не во всех) случаях полезно знать, какой тип отправил событие. Использование типа, отличного от object, для аргумента отправителя является слишком ограничительным: это будет означать, что другие отправители не смогут повторно использовать одну и ту же подпись события.

2 голосов
/ 20 сентября 2008

Крис Андерсон говорит в книге Руководства по проектированию фреймворка:

[T] это просто шаблон. Упаковав аргументы событий в классе, вы получите лучшую семантику управления версиями. Имея общий шаблон (sender, e), его легко узнать как сигнатуру для всех событий.

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

2 голосов
/ 19 сентября 2008

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

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

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

1 голос
/ 05 июля 2011

«Object sender» позволяет повторно использовать один метод для нескольких объектов, когда метод-обработчик должен что-то делать с объектом, вызвавшим событие, например, 3 текстовое поле может иметь один единственный обработчик, который будет сбрасывать текст текстового поля запуска .

Основным преимуществом EventArgs является то, что он позволяет проводить рефакторинг информации о событиях без необходимости изменять сигнатуры всех обработчиков во всех проектах, которые подписаны на это событие.

Я не могу придумать более разумного способа справляться с событиями.

1 голос
/ 19 сентября 2008

Казалось, что это был способ Microsoft развивать модель событий с течением времени. Также кажется, что они также позволяют другой способ сделать это с «новым» делегатом Action и его вариантами.

0 голосов
/ 14 марта 2011

Класс EventArgs сам по себе бесполезен, поскольку он должен быть создан для создания экземпляров любого содержимого. Это указывает на то, что подкласс должен использоваться, и многие из них уже существуют в .NET. К сожалению, я не могу найти хороших общих.

Допустим, вы хотите делегировать ведение журнала на общее событие ... БЕЗ НАПИСАНИЯ СВОЕГО СОБЫТИЙ EventArgs. Это может показаться бессмысленным упражнением, но мне нравится использовать существующие функции. Вы можете передать свою строку через аргумент Object, но это идет вразрез с ее предполагаемым использованием. Попробуйте найти хорошую ссылку на подклассы EventArgs в Google, и вы придете в себя. (По крайней мере, я сделал.)

ReSharper немного помогает, так как при вводе «EventArgs» вы увидите список всех классов (в пределах вашей области использования / импорта), которые содержат строку «EventArgs». Просматривая список, вы увидите много классов без строковых членов. Когда вы добираетесь до ControlEventArgs , вы видите, что свойство Text может использоваться, но со всеми накладными расходами элемента управления Windows. ConvertEventArgs может быть полезно, так как вы передаете тип вместе с данными, но для этого все же требуется тесная связь, которая не является ни хорошо документированной, ни по сути безопасной для типов. DataReceivedEventArgs не имеет реализации. EntryWrittenEventArgs требует EventLogEntry с байтовым массивом или StreamingContext для данных. ErrorEventArgs ближе, с сообщением об исключении, если вы не возражаете, вызывая все ваши события журнала Exception ErrorEvents для внутреннего использования. FileSystemEventArgs , вероятно, самый близкий, с двумя строками и обязательным аргументом перечисления WatcherChangeTypes, который МОЖЕТ быть установлен в 0, если вы знаете, что делаете. LabelEditEventArgs использует int и строку, если вы не возражаете против необходимости пространства имен Windows.Forms. RenamedEventArgs аналогичен FileSystemEventArgs с дополнительной строкой. Наконец, ResolveEventArgs в System.Runtime.InteropServices передает одну строку. Есть и другие библиотеки, но я остановился на некоторых из наиболее распространенных. Поэтому, в зависимости от реализации, я могу использовать ErrorEventArgs , FileSystemEventArgs или ResolveEventArgs для ведения журнала.

0 голосов
/ 02 ноября 2009

Иногда вы хотели бы заставить всех своих потребителей событий использовать определенный параметр события, например, событие безопасности, которое передает логический параметр, true для хорошего, false для плохого. В этом случае вы хотите, чтобы ваш потребитель болезненно знал о новом параметре, то есть вы хотите, чтобы ваши потребители были связаны с этим параметром. Обратите внимание, что ваши потребители по-прежнему не связаны с вашим классом стрельбы, но не с вашим.

Я подозреваю, что этот сценарий применим к большому количеству случаев, и в этих случаях значение EventArgs значительно уменьшается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...