One thing that annoys me is that in the default event, Sender has an object type and therefore almost always requires manual rendering before we can use it. Fortunately, since VB now also supports dispersion in delegates, we can update the event signature so that the sender is strongly typed, see the event parameter; “sender as object” or “sender” as “T”,
Unfortunately, this does not work for existing declared events that senders have an object of type.
Now, one solution would be to create a fake EventHandler that internally takes care of the cast for you. I made a quick example:
struct EventHandler<TSender, TEventArgs> where TEventArgs: EventArgs { private readonly Action<TSender, TEventArgs> _delegate; public EventHandler(Action<TSender, TEventArgs> @delegate) { if (@delegate == null) throw new ArgumentNullException("@delegate"); _delegate = @delegate; } public static implicit operator EventHandler<TEventArgs>(EventHandler<TSender, TEventArgs> eventHandler) { return new EventHandler<TEventArgs>(eventHandler.Execute); } private void Execute(object sender, EventArgs e) { TSender typedSender = (TSender)sender; TEventArgs typedEventArgs = (TEventArgs)e; _delegate(typedSender, typedEventArgs); } }
which can be used as you expected it to be used:
class Program { event EventHandler<EventArgs> Test; static void Main(string[] args) { new Program().Main(); } void Main() { Test += new EventHandler<Program, EventArgs>(TestEventHandler); Test(this, EventArgs.Empty); } void TestEventHandler(Program sender, EventArgs e) { throw new NotImplementedException(); } }
Now, if I really want to use this, a lot of work remains. (The structure should behave exactly the same as the original delegate). However, I feel that there is either an already excellent implementation there or no implementation, as there are some basic flaws that I have overlooked.
Who can answer this question? Any other clues?