Параметр события;«Отправитель как объект» или «Отправитель как T»? - PullRequest
13 голосов
/ 09 февраля 2011

Когда я пишу публичные события для своих бизнес-объектов, я адаптировал привычку всегда передавать экземпляр как « отправитель как объект », в дополнение к дополнительным специфическим параметрам.Я просто спросил себя сейчас почему я не указываю класс ?

Так что для вас с большим опытом; Вы когда-нибудь передавали отдельный класс в качестве отправителя в событии ?И если да, то каковы ваши критерии принятия решения , когда все в порядке / не в порядке?

Ответы [ 8 ]

11 голосов
/ 09 февраля 2011

Не будь экстремальным.EventHandler(object sender, EventArgs e) имеет отправителя объекта, поэтому мы можем использовать его во многих случаях.Но это не значит, что типизированный отправитель - это зло.Строго типизированный отправитель полезен, когда этот делегат не будет широко использоваться (например, EventHandler), например

public delegate void SaveHandler(Controller sender, EventArgs e);

Теперь другие разработчики (или кто-то, использующий вашу библиотеку) могут признать, что отправитель должны быть Controller, и они будут рады не кодировать вот так:

public void MySaveHandler(object sender, EventArgs arg)
{
   var controller = sender as Controller;
   if (controller != null)
   {
       //do something
   }
   else
   {
       //throw an exception at runtime? 
       //It can be avoided if sender is strongly-typed
   }
}

И вы даже можете сделать его универсальным:

public delegate void SaveHandler<T>(T sender, EventArgs args) 
                                              where T: IController;

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

5 голосов
/ 09 февраля 2011

Существует руководство по разработке , в котором указано, что обработчик событий должен иметь два параметра: sender (объект) и e (EventArgs или производные от него).

1 голос
/ 09 февраля 2011

Некоторое время назад было много дискуссий по связанному вопросу о StackOverflow.Вот этот вопрос: Подпись события в .NET - с использованием строго типизированного отправителя

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

Кроме того, с .NET 3+ и введением ковариации и контравариантности делегата не должно быть проблемой использование строго типизированного делегата.Должен признать, что в своем коде я неоднократно использовал строго типизированные обработчики событий.

Как я уже говорил ранее, все сводится к предпочтениям;Microsoft только что выпустила набор направляющих строк, а не правил ...

1 голос
/ 09 февраля 2011

Рекомендуется использовать подпись object sender, EventArgs e, так как метод может обрабатывать любые события этой подписи. Например, в проекте, использующем элемент управления диаграммами, есть несколько типов событий MouseOver - от DataSeries, от Legend, от всего Canvas.

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

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

1 голос
/ 09 февраля 2011

Моя текущая философия заключается в том, чтобы поддерживать методы работы с кодом как можно ближе к стандартному способу Microsoft. Вы получаете две вещи из этого:

  • Новые разработчики могут быстро понять ваш код
  • Вы обучаете существующих разработчиков, как работает остальная часть фреймворка
1 голос
/ 09 февраля 2011

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

На самом деле не отвечает на ваш вопрос о критериях принятия решения, но надеюсь, что это поможет

1 голос
/ 09 февраля 2011

Там нет такого ограничения.Это просто рекомендация, которой придерживаются в BCL (Base Class Library) и других популярных фреймворках.

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

0 голосов
/ 09 февраля 2011

Для вас не обязательно иметь такую ​​реализацию. Обычно это делается из-за того, что EventHandler делегат был разработан с таким прототипом.

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

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

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

Как это:

public delegate void MyEventHandler( MyType sender, EventArgs e);

Затем используйте его там, где требуется:

this.MyEvent += new MyEventHandler(my_eventhandlerfunction);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...