Alex Rivera | Logout

What would I lose by abandoning the standard EventHandler pattern in .NET?

Asked 2009-07-13T16:20:04.040
23

There's a standard pattern for events in .NET - they use a delegate type that takes a plain object called sender and then the actual "payload" in a second parameter, which should be derived from EventArgs.

The rationale for the second parameter being derived from EventArgs seems pretty clear (see the .NET Framework Standard Library Annotated Reference). It is intended to ensure binary compatibility between event sinks and sources as the software evolves. For every event, even if it only has one argument, we derive a custom event arguments class that has a single property containing that argument, so that way we retain the ability to add more properties to the payload in future versions without breaking existing client code. Very important in an ecosystem of independently-developed components.

But I find that the same goes for zero arguments. This means that if I have an event that has no arguments in my first version, and I write:

public event EventHandler Click;

... then I'm doing it wrong. If I change the delegate type in the future to a new class as its payload:

public class ClickEventArgs : EventArgs { ...

... I will break binary compatibility with my clients. The client ends up bound to a specific overload of an internal method add_Click that takes EventHandler, and if I change the delegate type then they can't find that overload, so there's a MissingMethodException.

Okay, so what if I use the handy generic version?

public EventHandler<EventArgs> Click;

No, still wrong, because an EventHandler<ClickEventArgs> is not an EventHandler<EventArgs>.

So to get the benefit of EventArgs

Edit
Report

1 Answer

7

Nothing, you lose nothing. I've been using Action<> since .NET 3.5 came out and it is far more natural and easier to program against.

I don't even deal with the EventHandler type for generated event handlers anymore, simply write the method signature you want and wire it up with a lambda:

btnCompleteOrder.OnClick += (o,e) => _presenter.CompleteOrder();
answered 2009-07-13T16:52:30.650

Your Answer