Should EventHandler always be used for events? - c#

I've been merrily writing events using custom delegate types and the generic Action delegate type, without really thinking about what I was doing.
I have some nice extension helpers for Action and EventHandler which makes me tend to use those predefined delegate types rather than my own, but aside from that...
Is there a good reason other than convention to favour EventHandler and EventHandler<T> over custom delegate types or generic Action delegate types?

The main advantage of the signature EventHandler<T> over using one parameter for each member of your EventArgs is that you can add additional properties to your EventArgs without breaking compatibility.
IMO this is the most important argument. Being able to extent your EventArgs without breaking subscribing code is very nice. But of course you can achieve the same with any signature that uses some kind of property-bag parameter instead of a parameter per property.
Then there is variance, EventHandler<Base> is convertible to EventHander<Derived>, so you can write an EventHandler with parameter EventArgs and it can subscribe to events which have more specific EventArgs.
Extension methods are another plus, but you already mentioned that.

No, no good reason.
If your events do not require EventArgs or a sender object, then you don't need to use EventHandler or EventHandler<T>.

The reason EventHandler is convention is that it supports a unified way of working with events.
The EventHandler for example always has a sender which comes out handy.
Rule of thumb here is that when you are working with WinForms and creating custom controls or extending e.g. Form, you really should use EventHandler. For your own classes: go wild.

Related

Packing event arguments in a class, why?

Most .NET stock events are have this signature:
delegate void SomethingSomething(SomethingEventArgs e);
event SomethingSomething OnSomethingSomething;
and
class SomethingEventArgs
{
public string Name;
public int Index;
public double Groar;
}
Why is that better (obviously is, otherwise anyone would choose to do) than:
delegate void SomethingSomething(string Name, int Index, double Groar);
event SomethingSomething OnSomethingSomething;
since you don't have to pack your parameters to an object, and without initializers (.NET 2.0) it was kind of typing exercise.
One reason that comes to mind is that you can return your values simpler when having them packed in an object - ie. handler can modify a member of the object. However, with multicast events, that can't always be good anyway.
So, why?
Read about Open/Closed principle.
By using a class, all inherited classes can introduce extra functionality without having to change the delegate signature. They can simply introduce a new event class (ExtendedEventArgs) which inherits yours (SomeEventArgs).
The main reason is that it is more maintainable. If you pass an objects and any of the properties change, you only have to modify that. If you pass variables, that is a lot more work. So, the code gets more maintainable and more readable this way.
A quote from Microsoft's Code Complete:
Limit the number of a routine’s parameters to about seven. Seven is a
magic number for people’s comprehension. Psychological research has
found that people generally cannot keep track of more than about seven
chunks of information at once (Miller 1956). This discovery has been
applied to an enormous number of disciplines, and it seems safe to
conjecture that most people can’t keep track of more than about seven
routine parameters at once.
In practice, how much you can limit the
number of parameters depends on how your language handles complex data
types. If you program in a modern language that supports structured
data, you can pass a composite data type containing 13 fields and
think of it as one mental “chunk” of data. If you program in a more
primitive language, you might need to pass all 13 fields individually,
If you find yourself consistently passing more than a few arguments,
the coupling among your routines is too tight. Design the routine or
group of routines to reduce the coupling. 1f you are passing the same
data to many different routines, group the routines into a class and
treat the frequently used data as class data.
Quoted text from the original post's image
The reason for this is to avoid breaking changes. For example, your class may wish to include further information with it's event, however every thing which used that event would break, as the delegate no longer matched. By having a strict delegate, your event can encapsulate more information in the future without affecting any subscribers.
Edit: As per the comments I'll expand on how this affects the reduction of breaking changes.
If we wished to add further information to our raised event, by using a single class derived from EventArgs new properties/methods can be added. This will mean any existing subscribers to the event will require no change, as the addition of these properties does not affect them. The only required change would be where these properties are set/used, e.g. where the event is raised.
The benefit is the pattern; and having a pattern gives both consistency and the the ability to use other APIs across multiple event types:
The EventHandler<T> delegate type (you don't need to define your own delegate type).
The Reactive Extensions (Rx) have conversion of an event into an IObservable<T> allowing use of LINQ on event sources with Observable.FromEvent.
Also you've got the signatures wrong:
The delegate takes two arguments: object source and SomethingEventArgs
The SomethingEventArgs type inherits EventArgs.
Thus your code should be, to be an exemplar of the pattern:
At namespace scope:
public class SomethingEventArgs : EventArgs {
public string Name;
public int Index;
public double Groar;
}
public delegate void SomethingSomething(object source, SomethingEventArgs e);
and in the type exposing the type
public event SomethingSomething OnSomethingSomething;
(An event could also be internal.)
As others have pointed out, there are maintainability and concistency reasons for this. The EventArgs approach also makes it possible for the event handler to modify the EventArgs.
One reason for modifying the EventArgs is errorhandling. An exception caught somewhere on a background thread is communicated to the client as an event. The client can set a flag in the EventArgs to indicate the exception was handled an shouldn't be rethrown on the background thread.
Another example is the ObjectDataSource class that lets the client supply an object instance when one is required. This is done by subscribing to the ObjectDataSource.ObjectCreating event and supplying the object instance by setting a member of the EventArgs.
Using a class allows the event's subscribers to effect the outcome.
When you pass an instance of a class as a parameter to a method, it is passed by reference. This allows the object instance to change during the method call. Those changed values can then be read by the caller after the event is raised.
For instance:
Look at the FormClosingEventHandler Delegate (in Windows Forms).
This delegate uses a parameter of type FormClosingEventArgs.
If a subscriber to an event using this delegate sets the Cancel property (inherited by CancelEventArgs) to true, then the form is not closed.
In addition, these answers are also correct:
jgauffin
Baszz
Firstly, the reason why this pattern is so common (as you have asked) is because Microsoft has specifically prescribed so when they developed the Event Pattern (yes they coined this term, too). I don't necessarily think this is better or worse than coming up with your own delegate signatures, but following a well-known convention can have its advantages.
Per Microsoft:
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.
The method takes exactly two parameters.
To get more at the point of your question, though, I think the rationale for using EventArgs is twofold:
So that classes that inherit from your class can still raise the event, with a derived EventArgs class.
So that classes that handle your event can use common event handlers to handle several types of events, even if different events use different EventArgs. Or, if you change the event down the road, any classes that already handle the event don't need to change their code because the handlers will still be compatible with the new event.
For further reading, see more info from Microsoft:
More info about how to design events: http://msdn.microsoft.com/en-us/library/ms229011.aspx
A detailed how-to on using this pattern: http://msdn.microsoft.com/en-us/library/w369ty8x.aspx
In order to follow the .net standards, the recommanded way to create an event is:
Create a class that inherits from EventArgs
Use the EventHandler<T> generic delegate
As doing so reduces the amount of work required to subsequently change the number and types of values sent to event subscribers.
Example:
public event EventHandler<SometingEventArgs> SomethingEvent;
class SomethingEventArgs
{
public string Name;
public int Index;
public double Groar;
}
In addition to the backward-compatibility convention that others have already mentioned, the EventArgs class enables more control over how the parameters are contiguously accessed as they are passed to more than one object.
This control can be used to make certain values immutable, so that if an event is sent to 3 different subscribers you can guarantee it's not tampered with.
At the same time you can offer multiple [out] values, and you don't have to juggle return values or [ref] parameters, which significantly complicates the multicasting process. It also ensures that any validation logic occurs in the EventArgs subclass, NOT in the class that fires the events.

Should I use EventArgs or a simple data type?

I'm currently creating a library for fun and practice and I was wondering, when raising an event, how to choose between passing your own EventArgs derivative or just the data type.
For example, in my library I have something like this:
public delegate void LostConnectionEventHandler(string address);
public delegate void MessageReceieved(byte[] bytes);
What is the standard practice for this? Should I replace string address with ConnectionEventArgs and byte[] bytes with MessageEventArgs?
I know either one works just fine and this question may be subjective but I am still curious on the thought process higher-level programmers go through when deciding whether or not to include their own EventArgs or just to pass the data in directly.
Thanks!
The .NET Framework guidelines indicate that the delegate type used for
an event should take two parameters, an "object source" parameter
indicating the source of the event, and an "e" parameter that
encapsulates any additional information about the event. The type of
the "e" parameter should derive from the EventArgs class. For events
that do not use any additional information, the .NET Framework has
already defined an appropriate delegate type: EventHandler.
Reference: http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx
Another useful information: http://msdn.microsoft.com/en-us/library/ms229011.aspx
Personally I like the idea of deriving from EventArgs,
if you have to pass status information and aggregate objects you could easily do it, see the
MouseEventArgs type for example.
using OOP approach, if you have an event/construct which accepts an object of type EventArgs you can rely on the fact that every object derived from it will work in the same way while if you have another kind of object which does not share the same base class, you could eventually break something.
hard to prove and reproduce but possible depending on the design, because events are special delegates designed to work with EventArgs and its descendants
In a larger project, having an EventArgs class, helps with minimizing the code you have to modify, when your event needs additional data in some cases. I usually prefere the EventArgs way instead of a direct value.
Within my projects I use EventArgs when the number of parameters is larger than one! Look at the NotifyPropertyChanged Event, it has one argument, which isn't an EventArgs type.
There's no need to derive from EventArgs however the convention follows the common (Introduce Parameter Object) refactoring rule. And the rationale for this rule is well documented.
I generally disagree with the "hide your args" guideline. Hiding arguments in a contrived object removes a lot of meaning and context from the event signature, making developers hunt for it. And why? Just to avoid something we do all the time with methods: update call sites when an argument is added. That's just not a big deal. If it were, we'd also hide method arguments in a "MethodArgs" parameter. The readability loss isn't worth it in most cases.

Two questions regarding events

I would like to know:
Subscriber is a name for class that subscribes for the event or also for the method that is handling the event? I mean, does it make sense to say "subscribe method to event"?
On MSDN it says that event delegate should have exactly 2 arguments. Not sure what it means as I often create events with my custom delegate that has e.g. none or one argument.
1) Yes, it definitely makes sense to talk about subscribing a method to an event. You can actually think of there being three entities involved:
The subscribing code which is actually performing the subscription itself
The event publisher
The handler which is being subscribed; this is often - but not always - code in the same class as the subscribing code
2) You certainly can create events using delegates with any number of parameters. The convention is that delegates used in events have two parameters: a "sender" and an "argument" derived from EventArgs. For example, this means that you can subscribe a handler from a method with a signature of void Foo(object sender, EventArgs e) to any event following the convention.
A subscriber is a method that is added as an event handler.
Standard practice is to use the EventHandler<T> delegate for events; this has two arguments.
However, you can create your own events with any number of arguments.
I'll concentrate on the second point. As Jon pointed out, you can use your own delegates for events. But you rarely should. Even if you don't care about conventions, look at it this way: whenever you use your own events with custom delegates, you have the following code besides the event field itself:
Your custom delegate
Event handlers (methods with matching signature) - sometimes a lot of them
Event invocation points (where you need to pass all the parameters)- sometimes a lot of them
I also tend to create the InvokeMyEvent methods that do the nullity checking and other stuff that needs to be done
You have to change all of these if you decide to add or remove a parameter or change a parameter type.
Now, if you create your own class that inherits EventArgs or use the EventArgs<T>, you have:
Your CustomEventArgs class
Event handlers
Event invocation points
InvokeMyEvent methods.
Whenever you decide to change the event args you have to change only your custom args class and some of the event invocation points. "Some", because you can provide suitable default values for fields of your args class and only provide the values when you need it.
Most of good/bad practice talks are focused on one thing - ease of change. Changes always happen. The fewer things you have to alter when they do, the better. Design has a lot of iterations and the odds are that you'll have to change your interfaces and types a lot. You don't want to change tens of signatures whenever you decide that you don't need the parameter anymore. So use the EventArgs or EventArgs<T> and save yourself some headache.
Another minor point is that you'll probably want to declare some methods that take care of raising the events, like this:
public static public void FireEvent<T>(this EventHandler handler, object sender, EventArgs<T> e)
where T : EventArgs
{
if (handler != null)
handler(sender, e);
}
If all your events are EventHandler-based, you can use one all-purpose method for things like that. If not, then you'll eventually have tens of them.

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

When I write public events for my business objects, I've adapted the habit of always passing the instance as "sender as Object", in addition to additional specific parameters. I just asked myself now why am I not specifying the class?
So for you with more experience; Do you ever pass the distinct class as sender in an event? And if so, what are your decision criteria for when this is ok/not ok?
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.
There is a design guideline that specified that an event-handler should have two params: sender (an Object) and e (EventArgs or derived from that).
There no such restriction. It is just a guideline that is followed throughout BCL (Base Class Library) and other popular frameworks.
I would recommend you follow it to keep it consistent if it is going to be used by other developers or be released as a framework.
As far as I see it you can either create delegates with the parameters you want and then create an event using that delegate and then you can call the event and pass the parameters in or you can use Custom Event Argument as shown here. As the other answer suggests. Keep it consistent.
Doesn't really answer your question about the decision criteria but hope it helps
My current philosophy is to keep code practices as close to the standard Microsoft way as possible. You get two things from this:
New developers can quickly understand your code
You train existing developers how the rest of the framework works
It is good practice to use the object sender, EventArgs e signature, as the method can handle any events of that signature. For example, in a project using a charting control, there are several types of MouseOver events - from a DataSeries, from the Legend, from the whole Canvas.
That way, you can handle any source of the event, as at most times, the information is in the EventArgs.
Also, you don't have to cast the sender when passing it to the delegate, as any class instance is an object deep down.
There was a lot of discussion on a related question on StackOverflow some time ago. Here is that question: Event Signature in .NET -- Using a strong-typed sender
Eventually, it comes down to preference. In most cases, you'd like your event handlers to be bound to a particular type of class so making the sender an object and then casting back to the class in order to get access to its properties might not go down well with you [it doesn't go down well for me either].
Besides, with .NET 3+ and the introduction of delegate covariance and contravariance, it should not be a problem to use a strongly typed delegate. I must admit, I've used strongly typed event handlers more than once in my code.
Like I said earlier, it comes down to preference; Microsoft just issued a set of guidelines not rules...
It is not a binding on you to have such implementation. Its usually done because of the EventHandler delegate was designed with such prototype.
Its a simple guideline followed through Base Class Library. But sure you can make you own Parameters and implementations.
But remember if it is to be used by some developer other that you, he will need to know about such implementation. Its don for greater good and flexibility to use an event anywhere irrespective of class its used in.
If you define a Custom Prototype for event then i would suggest that you also define Custom Delegate that will ensure you will have catch an exception if proper type is not passed. (User will need to do an Explicit cast if required)
Like this:
public delegate void MyEventHandler( MyType sender, EventArgs e);
Then use it where required as:
this.MyEvent += new MyEventHandler(my_eventhandlerfunction);

Benefits of events using EventArgs/EventArgs<T> delegate types instead of…

I understand the benefits of events using delegate types with signature delegate void delegate_name(object sender, EventArgs e)
a) But besides the fact that it may save us some typing, are there any other reasons why we should use already defined delegate types EventHandler/EventHandler<T> instead of declaring our own delegate types with signature delegate void delegate_name(object sender, EventArgs e)?
b) Two other reason I can think of for using the predefined delegate types EventArgs/EventArgs<T> are:
people consuming particular event ( say event EventHandler my_event ) will immediately know how to use that event?
perhaps some popular third party methods accept as parameters EventHandler/ EventHandler<T> delegate types, and thus if there’s any chance that our code may use those third party methods, we should use predefined delegates EventHandler/Eventhandler<T>?
thank you
To me, the question is a little strange. What would be the benefit of doing this otherwise (defining delegate types that exactly match EventHandler<TEventArgs> for some TEventArgs)?
That said, there is at least one benefit I can think of to doing it the "normal" way: certain APIs already expect to deal with EventHandler<TEventArgs> delegates; for example, Rx Extensions includes a method that looks like this:
Observable.FromEvent<TEventArgs>(
Action<EventHandler<TEventArgs>> addHandler,
Action<EventHandler<TEventArgs>> removeHandler
);
If you defined your own delegate, using methods like this -- which expect EventHandler<TEventArgs> delegates -- would become more complicated than necessary for no added benefit (that I can see, anyway).
You forgot an important one:
the lunatic that will maintain your code some day will find out where you live and hurt you.
You've answered your own question:
Syntactical Sugar (less to write) to maintain the convention
Interoperability (using the EventHandler type let's you easily integrate events from other libraries
In short; there's no good reason not to use it unless you're forced to (which typically is the result of people not being aware of it, or not understanding it).
From Pro C# 2008 and the .NET 3.5 Platform:
When the compiler processes the event keyword, you are automatically provided
with registration and unregistration methods* as well as any necessary member
variables** for your delegate types. ...To be sure, the event keyword is
little more than syntactic sugar in that it simply saves you some typing time.
* This includes overloading the handy += and -= operators.
** ...which are already marked private so they can't end-run.
When you use the generic EventHandler delegate, you don't even have to write out your custom delegate type at all.
I'm going to rock the boat here and propose something entirely heretical. I used to be firmly in the EventArgs camp because I clung to the "MS recommends this and it's always been done this way" mentality, but over time I came to hate EventArgs. Why?
It promotes a .NET-1.0ish style of coding which relies upon weak-typing/type casting and makes me feel unclean.
It forces your class which implements the event to pollute the heap with new EventArg instances every time it fires, which also makes me uneasy. Why not have my events give subscribers exactly what they need instead of wrapping it up in an extra class that does nothing for me.
The signatures of your callback methods which subscribe to the event look like garbage and have very little semantic detail - e.g. object sender - WHAT is sender?!?!
What I do now is declare my own event handler delegates, which I store neatly in their own "Delegates" folder in my solution as well as their own namespace. So my delegate may reside in its own file like this:
namespace MyAPI.Data.Delegates
{
public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data);
}
The event declaration now looks like this:
public event DataEventHandler<TData> DataReady = delegate { };
Benefits to this approach:
Method signatures have more semantic detail. You know WHO is sending WHAT.
Strong-typing is preserved. No more casting object sender to what you think it should be.
You don't have to new() up objects and pollute the heap, which can be problematic if your event fires frequently. Just pass your subscribers exactly what they need, whether it be an object reference or a value type.
By using the ___EventHandler naming convention for your delegates, you are still promoting a uniform style for your code which makes it easy for users of your API to know what your intent is.
The only "drawback" is that it makes it hard for users of your code to wire up your event to existing methods which have the object sender, EventArgs e signature. However, this point is moot because if your event delivers any extra data (e.g. you created your own EventArgs subclass) then they'll have to change the method signature anyway (or cast to your subclass type). Either way, that's still nasty.
That's why I like my way.

Categories

Resources