Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a C# event handler, why must the "sender" parameter be an object?

Tags:

c#

events

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"

like image 576
Iain Galloway Avatar asked Sep 17 '09 09:09

Iain Galloway


People also ask

What AC means?

AC stands for air conditioning.

What is the meaning of AC and AC?

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.

Why is there a slash in AC?

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."

What is an AC code?

AC. Authentication Code (telecommunications)


2 Answers

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...

like image 138
Jon Skeet Avatar answered Sep 23 '22 02:09

Jon Skeet


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.

like image 34
Keith Avatar answered Sep 24 '22 02:09

Keith