According to Microsoft event naming guidelines, the sender
parameter in a C# event handler "is always of type object, even if it is possible to use a more specific type".
This leads to lots of event handling code like:
RepeaterItem item = sender as RepeaterItem; if (item != null) { /* Do some stuff */ }
Why does the convention advise against declaring an event handler with a more specific type?
MyType { public event MyEventHander MyEvent; } ... delegate void MyEventHander(MyType sender, MyEventArgs e);
Am I missing a gotcha?
For posterity: I agree with the general sentiment in the answers that the convention is to use object (and to pass data via the EventArgs
) even when it is possible to use a more specific type, and in real-world programming it is important to follow the convention.
Edit: bait for search: RSPEC-3906 rule "Event Handlers should have the correct signature"
AC stands for air conditioning.
uncountable noun. a/ c is an abbreviation for air-conditioning. Keep your windows up and the a/c on high. 60 Motel Units. All Units A/C, Heat, Cable TV.
Senior Member. You read it as "ei-cee" (no "slash" pronounced). In terms of distinguishing between "air conditioning" and "air conditioner," I can think of an example like "Today, I bought a new air conditioner" ("conditioning" not allowed). I personally would not say "Today, I bought a new AC."
AC. Authentication Code (telecommunications)
Well, it's a pattern rather than a rule. It does mean that one component can forward on an event from another, keeping the original sender even if it's not the normal type raising the event.
I agree it's a bit strange - but it's probably worth sticking to the convention just for familiarity's sake. (Familiarity for other developers, that is.) I've never been particularly keen on EventArgs
myself (given that on its own it conveys no information) but that's another topic. (At least we've got EventHandler<TEventArgs>
now - although it would help if there were also an EventArgs<TContent>
for the common situation where you just need a single value to be propagated.)
EDIT: It does make the delegate more general purpose, of course - a single delegate type can be reused across multiple events. I'm not sure I buy that as a particularly good reason - particularly in the light of generics - but I guess it's something...
I think there's a good reason for this convention.
Let's take (and expand on) @erikkallen's example:
void SomethingChanged(object sender, EventArgs e) { EnableControls(); } ... MyRadioButton.Click += SomethingChanged; MyCheckbox.Click += SomethingChanged; MyDropDown.SelectionChanged += SomethingChanged; ...
This is possible (and has been since .Net 1, before generics) because covariance is supported.
Your question makes total sense if you're going top-down - i.e. you need the event in your code, so you add it to your control.
However the convention is to make it easier when writing the components in the first place. You know that for any event the basic pattern (object sender, EventArgs e) will work.
When you add the event you don't know how it will be used, and you don't want to arbitrarily constrain the developers using your component.
Your example of a generic, strongly typed event makes good sense in your code, but won't fit with other components written by other developers. For instance if they want to use your component with those above:
//this won't work GallowayClass.Changed += SomethingChanged;
In this example the additional type-constraint is just creating pain for the remote developer. They now have to create a new delegate just for your component. If they're using a load of your components they might need a delegate for each one.
I reckon the convention is worth following for anything external or that you expect to be used outside of a close nit team.
I like the idea of the generic event args - I already use something similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With