I searched through the archives and I found lots of questions about what sender is and why you should use the pattern but I didn't see anything about a custom event and the type if sender.
Say I am creating a custom class called Subscription and it implements ISubscription and I have some event args called SubscriptionEventArgs. If Subscription had an event called Changed what is wrong about the event signature Changed(ISubscription sender, SubscriptionEventArgs e)?
A little code to help drive the question:
public class SubscriptionEventArgs : EventArgs
{
// guts of event args go here
}
public interface ISubscription
{
event Action<ISubscription, SubscriptionEventArgs> Changed;
}
public class Subscription : ISubscription
{
public event Action<ISubscription, SubscriptionEventArgs> Changed;
private void OnChanged(SubscriptionEventArgs e)
{
if (Changed!= null)
{
Changed(this, e);
}
}
}
If you just despise the use of action in place of "EventHandler" then you could do the same thing but with a custom generic "EventHandler".
public delegate void EventHandler<TSender, TEventArgs>(TSender sender, TEventArgs e);
public class SubscriptionEventArgs : EventArgs
{
// guts of event args go here
}
public interface ISubscription
{
event EventHandler<ISubscription, SubscriptionEventArgs> Changed;
}
public class Subscription : ISubscription
{
public event EventHandler<ISubscription, SubscriptionEventArgs> Changed;
private void OnChanged(SubscriptionEventArgs e)
{
if (Changed!= null)
{
Changed(this, e);
}
}
}
In response to Hans' request for a sample event handler:
public class SubscriptionCollection
{
// what is actually holding the subscriptions is not really relevant to the question
private List<ISubscription> _subscriptions;
public SubscriptionCollection()
{
_subscriptions = new List<ISubscription>();
}
public void Add(ISubscription subscription)
{
subscription.Changed += new EventHandler<ISubscription, SubscriptionEventArgs>(Subscription_Changed);
_subscriptions.Add(subscription);
}
private void Subscription_Changed(ISubscription sender, SubscriptionEventArgs e)
{
// Now when the subscription changed event is being handled by the collection
// I don't have to look up the subscription in the list by some key and I don't
// have to cast sender to the correct type because the event handler was typed
// correctly from the beginning.
}
}
The lookup of the subscription in the list might seem trivial but what if I am working with very large sets of data and new volumes of data are coming at the application through a real-time stream. The cost of having to stop and get a reference out of a list or go through the steps of casting don't make sense. They gave us generics in 2.0 to solve that issue so I don't understand why we didn't get a generic event handler too and this led me to question what is wrong with a generic event handler?