Event Signature in .Net -- Using a Strong Typed 'Sender'

Event Signature in .NET -- Using a Strong Typed 'Sender'?

It seems Microsoft has picked up on this as a similar example is now on MSDN:

Generic Delegates

Why do .NET events have a sender parameter of type object and not of type T?

Because the universal signature of event handler methods was invented long before generics were ever added to the language.

Using System.Object was the logical choice in the days before generics, as it really was the most "generic" object available. All other objects ultimately derive from System.Object, including controls, BCL classes, and user-defined classes, because it is at the root of the type hierarchy.

EventHandler with a strongly typed sender in C#

I can't think of any solution that would have less code than

var original = (OriginalType)sender;

Also if class is yours nothing stops you from creating your own delegate instead of EventHandler delegate

delegate void EventHandler<in TSender, in TArgs>(TSender sender, TArgs args);

This is contravariant in args and sender

People usually also have the reference of the object for which the event is raised and therefore they rarely need to get the thing out of the sender. Could it be possible in your case?

Edit: Since you mentioned you're dealing with events that are not written by you so modifying the delegate is out of question and you probably don't have reference to the object so you have to resort to the sender in that case. Now in your solution you can not unsubscribe to the event. If you modify it to support that then you'll have to keep the reference to this struct of yours which is more work than simple casting. I think casting is still the cleanest solution.

Event parameter; sender as Object, or sender as T?

Don't be extreme. EventHandler(object sender, EventArgs e) has an object sender so that we can use it in many circumstances. But it doesn't mean a strongly-typed sender is evil. A strongly-typed sender is useful when this delegate is not going to be widely used(like EventHandler) e.g.

public delegate void SaveHandler(Controller sender, EventArgs e);

Now other developers(or someone using your library) can recogonize that the sender have to be a Controller, and they will be glad not to code like this:

public void MySaveHandler(object sender, EventArgs arg)
{
var controller = sender as Controller;
if (controller != null)
{
//do something
}
else
{
//throw an exception at runtime?
//It can be avoided if sender is strongly-typed
}
}

And you can even make it generic:

public delegate void SaveHandler<T>(T sender, EventArgs args) 
where T: IController;

It's pure legal and good practice in C#. You should make clear what you want to do, and then choose the better way. Either of them is evil/bad.

Event signature pattern in .net

It's mainly for consistency and versioning—with the sender paramater as always System.Object and the args parameter as always a System.EventArgs, or a dervied class thereof, you can change the sender argument passed to it as well as change the EventArgs type afterwards without breaking any existing code.

The whole .NET eventing idiom was designed to support component-based development, where the calling code is not under control of the developer of the component with the events.

C# simple Event Raising - using sender vs. custom EventArgs

The common pattern is to use sender and not add the sender separately to the EventArgs. The custom EventArgs is used for other state like a tree node for a tree event, a (settable) boolean for a cancelable event etc.

We use the common pattern since it is used by the BCL classes also, and making a difference for "self-made events" is potentially confusing. Also, we have a global IoC publisher-subscriber pattern but this one only works with the normal EventHandler delegate signature, since the types are not known in advance. In this case, a cast (for instance to a custom EventArgs) is necessary anyways, so we might just as well cast the sender.

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

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

Why do event handlers use Object Sender when being automatically created in Visual Studio

Its the control that gets to decide on the signatures for its events (what delegates it wants to use), and most event signatures always use a first parameter called sender of type object. That follows the guidelines:

  • The return type is Void.

  • The first parameter is named sender and is of type Object. This is the object that raised the event.

  • The second parameter is named e and is of type EventArgs or a derived class of EventArgs.This is the event-specific data.

You can use the same handler code to listen to multiple events from multiple controls, of different types, so it wouldn't be necessarily good to restrict the sender type.

These guidelines made a lot more sense before delegate variance was introduced in .NET 3.5.



Related Topics



Leave a reply



Submit