10

When programming events in C#, it is advised to create a delegate in form of:

delegate XEventHandler(object sender, XEventArgs e);

My question is on the first argument of the delegate, object sender. Does it always have to be a generic object? Having a sender of type object always results in code similar to this.

val = ((ConcreteType)sender).Property;

or, even more verbose,

ConcreteType obj = sender as ConcreteType
if (obj != null) { ... }

One argument against strongly typed senders is that other objects can forward the event without worrying about the type. While this might make sense in GUI environments, I am not sure if it could benefit outside a GUI.

What if the class of the sender is always known (at least as an abstract class)? For example, if I am implementing a ListChanged event in an abstract List class, and if other classes are going to inherit it (e.g. LinkedList, ArrayList), is it all right to define my delegate with a sender of type List?

delegate ListChangedEventHander(List sender, ListChangedEventArgs e);

Or, would there be a downside of changing the conventional object sender to a more specific type?

sampathsris
  • 565
  • 5
  • 17

2 Answers2

10

At this point, it is mostly a (pretty strong) convention. That is, it will be weird if you write a library that does not follow that convention.

The Event Design Guidelines say:

DO use object as the type of the first parameter of the event handler, and call it sender.

However, you may note that current guidance says that you should not define your own custom delegate for events, but use EventHandler<T> instead, if you can.

As for the design, I would guess that it also promotes the reuse of event handlers, even in contexts not originally foreseen by the original designer of the event.

jhominal
  • 1,448
  • 10
  • 17
  • 2
    Ughhh...just because Microsoft decided to make their guidelines generic enough to be applicable to everybody, doesn't mean it is a good idea for everybody else to follow their guidelines. Odds are extremely likely that "everybody else" isn't writing code to be used by millions of other developers. I cringed at about 2/3's of the recommendations from the link you provided. – Dunk Oct 28 '14 at 14:46
  • To tell you the truth, this "guideline" more or less feels like Windows API's Hungarian notation. Someone brilliant started it for a really good reason and then everybody else started to abuse it. When there's a guideline, there better be a good reason behind that guideline. And what _I_ think the reason for this guideline is that `System.Windows.Forms` namespace is the place where events are most heavily used, and it made sense to subscribe to the `Click` event of `Button` or a `CheckBox`. Thus the sender _needs_ to be generic. ... – sampathsris Oct 28 '14 at 14:58
  • ... But when it comes to other, more specific, contained areas of functionality, sender might need not to be a generic class. See again my example of a class hierarchy of `List`s. – sampathsris Oct 28 '14 at 15:00
  • @Dunk: I cringe at the idea of defining and using events. The event feature has been superseded by Microsoft libraries multiple times (see WPF routed events/WPF change notification/WPF weak events, Prism events, Reactive Extensions), for in my opinion good reasons. Still, if I write events in my library, I will make sure to follow these guidelines in order to reduce the learning curve for users of the library. (If I know my users have a reasonable tolerance for less conservative choices, I will use an observable instead of an event). – jhominal Oct 28 '14 at 15:13
  • 11
    @Dunk: And that's the point. This guideline comes from Framework Design Guidelines, which is primarily concerned with code *consumed by others*. Not because it's the best solution, but because it's the least surprising. That's the best option *for a framework*. For smaller libraries, if the use-case is well specified, less of the guidance is applicable. Microsoft explicitly says so at the beginning of the book. – Magus Oct 28 '14 at 16:26
  • 1
    I'm not arguing with the answer, I even upvoted it because it comes from a reputable source. I'm just saying that I wouldn't use the guidelines. If an event is supposed to send specific data then I'll just send the specific data. Also, the event feature works just fine if you use them how they were intended to be used. – Dunk Oct 28 '14 at 20:28
0

The reason for the recommendation is that it allows for future changes that do not necessarily require changes to existing code, and especially the public interface.

The event mechanism itself can still be used for "VB6"-style events, but you'll have to change all existing consumers if you ever need to change the signature (or worse: create new versions of the same events). With the recommended approach, as long as the newer items inherit from the existing ones, you can update the signature without fixing existing code.

Mark Hurd
  • 343
  • 1
  • 3
  • 12