Меня раздражает то, что в событии по умолчанию Sender имеет тип object и поэтому почти всегда требует ручного приведения, прежде чем мы сможем его использовать. К счастью, поскольку VB теперь также поддерживает вариативность в делегатах, мы можем обновить подпись события таким образом, чтобы отправитель был строго типизирован, см. Параметр события; «отправитель как объект» или «отправитель как T»?
К сожалению, это не работает для существующих объявленных событий, отправители которых относятся к типу объекта.
Одним из решений, конечно же, было бы создание поддельного EventHandler, который внутренне позаботится о приведении типов за вас. Я сделал быстрый пример, см.:
struct EventHandler
where TEventArgs: EventArgs
{
private readonly Action _delegate;
public EventHandler(Action @delegate)
{
if (@delegate == null)
throw new ArgumentNullException("@delegate");
_delegate = @delegate;
}
public static implicit operator EventHandler(EventHandler eventHandler)
{
return new EventHandler(eventHandler.Execute);
}
private void Execute(object sender, EventArgs e)
{
TSender typedSender = (TSender)sender;
TEventArgs typedEventArgs = (TEventArgs)e;
_delegate(typedSender, typedEventArgs);
}
}
, который можно использовать так, как вы ожидаете от него:
class Program
{
event EventHandler Test;
static void Main(string[] args)
{
new Program().Main();
}
void Main()
{
Test += new EventHandler(TestEventHandler);
Test(this, EventArgs.Empty);
}
void TestEventHandler(Program sender, EventArgs e)
{
throw new NotImplementedException();
}
}
Теперь, если я действительно хочу использовать это, нужно проделать много работы. (Структура должна вести себя так же, как исходный делегат). Тем не менее, у меня есть ощущение, что либо уже существует отличная реализация, либо ее нет, поскольку есть некоторые серьезные недостатки, которые я упустил.
Кто может мне ответить на этот вопрос? Какие-нибудь другие подсказки?