#c# #generics
#c# #обобщения
Вопрос:
Предполагая, что у вас есть такой метод, как этот
private void FireEvent<T>(EventHandler<T> eventHandler, T eventArgs, string name)
{
var handler = eventHandler;
if (handler != null)
{
Console.WriteLine(String.Format("Sending event {0}", name));
handler(this, eventArgs);
}
else
{
throw new UnconnectedEventException(name);
}
}
Можно ли переписать / перегрузить / расширить этот метод, чтобы он принимал оба EventHandler<T> and EventHandler
( eventArgs
например, может быть EventArgs.empty
в последнем случае)?
Текущим решением является этот дополнительный метод:
private void FireEvent(EventHandler eventHandler, string name)
{
var handler = eventHandler;
if (handler != null)
{
Console.WriteLine(String.Format("Sending event {0}", name));
handler(this, EventArgs.Empty);
}
else
{
throw new UnconnectedEventException(name);
}
}
Но это включает в себя копирование каждой строки реализации с одним незначительным отличием, которое убивает меня изнутри. Несомненно, должно быть лучшее решение.
Примечание: Во втором примере срабатывает an EventHandler
, а не an EventHandler<EventArgs>
. Эти два типа не могут быть преобразованы друг в друга, поскольку они являются несвязанными делегатами.
Комментарии:
1. можете ли вы просто вызвать fireEvent<object>() ?? Достаточно просто написать функцию-оболочку без универсального аргумента <T> и просто вызвать ваш универсальный метод, используя только object и EventArgs.Empty .
2. Вы пробовали просто добавить метод с требуемой подписью? Если это так, пожалуйста, опубликуйте полученные ошибки (если таковые имеются).
3. Делегаты не имеют наследования, поэтому
EventHandler<T>
иEventHandler
являются принципиально разными типами, которые нельзя обработать одним методом. Но по той же причине нет проблем сFireEvent(EventHandler eventHandler, EventArgs eventArgs string name)
перегрузкой. Если вы действительно считаете, что стоит выделить логику, вы можете извлечьhandler(this, eventArgs)
вызов как anAction
, но это приведет к потере эффективности.4. Поскольку тип
eventArgs
аргумента (theT
) будетEventArgs
, объявите обработчик события какEventHandler<EventArgs>
. Я также поддерживаю предложение просто использовать отдельный метод. Только не пытайтесь использовать один метод для выполнения двух отдельных действий только потому, что они кажутся похожими.
Ответ №1:
Я бы сказал, что самое короткое правильное решение, которое не копирует код или игнорирует EventArgs
:
private void FireEvent<T>(EventHandler<T> eventHandler, T eventArgs, string name)
{
if (eventHandler == null) throw new UnconnectedEventException(name);
Console.WriteLine(String.Format("Sending event {0}", name));
eventHandler(this, eventArgs);
}
private void FireEvent(EventHandler eventHandler, EventArgs eventArgs, string name) =>
FireEvent(eventHandler == null ? null : new EventHandler<EventArgs>(eventHandler), eventArgs, name);
(Стандартный шаблон первого назначения обработчика события локальной переменной для потокобезопасности здесь не нужен, поскольку мы уже неявно скопировали его как часть вызова метода.)