Packing event arguments in a class, why? - c#

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.

Related

Sending relevant data by parameter or access with getter?

Especially in the case of events I was wondering if there's a good reason to choose one over the other?
C# example:
Class A
public event System.Action<someparam> someevent;
Class B
void eventcalledmethod(someparam param){
//do something with param
}
Vs.
Class A
public event System.Action();
public static someparam Getter{get;}
Class B
void eventcalledmethod (){
//do something with A.Getter
}
The second example is used in the Microsoft Windows C++ API for the handling of window events.
Answering as I'd argue that this is not a matter of style, as the first method provides different functionality to the second (ignoring doing silly things that you wouldn't normally do anywhere else in your code base).
The first method has the benefit of being able to pass information about a specific instance of A (or any other information required for the event). This is idiomatic and follows normal OOP practices regarding polymorphism and encapsulation. In terms of patterns, it allows for dependency injection amongst other things.
The second method ties the event handling to a static property of A, meaning each instance of A cannot have it's own values for that. It's also not idiomatic, in that most programmers expect the event to contain all information needed for handling the event - tying the handling to a static property adds unnecessary coupling.
I know this might seem like a style argument, but I'd really argue the first is simply more flexible and as such should be preferred where possible.

Events aren't fields - I don't get it

In C# in depth (an excellent book thus far), Skeet explains events aren't fields. I read this section many times and I don't understand why the distinction makes any difference.
I am one of those developers that confuse events and delegate instances. In my mind, they are the same. Aren't both just a form of indirection? We can multicast both. An event is setup as a field as shorthand...sure. But, we are adding or removing handlers. Stacking them up to be called when the event fires. Don't we do the same thing with delegates, stack them up and call invoke?
The other answers are basically correct, but here's another way to look at it:
I am one of those developers that confuse events and delegate instances. In my mind, they are the same.
An old saying about not seeing the forest for the trees comes to mind. The distinction that I make is that events are at a higher "semantic level" than a field of delegate instance. An event tells the consumer of the type "hi there, I am a type that likes to tell you when something happens". The type sources an event; that's part of its public contract.
How, as an implementation detail, that class chooses to keep track of who is interested in listening to that event, and what and when to tell the subscribers that the event is happening, is the business of the class. It happens to typically do so with a multicast delegate, but that's an implementation detail. It is such a common implementation detail that it is reasonable to confuse the two, but we really do have two different things: a public surface, and a private implementation detail.
Similarly, properties describe the semantics of an object: a customer has a name, so a Customer class has a Name property. You might say that "their name" is a property of a customer, but you would never say that "their name" is a field of a customer; that's an implementation detail of a particular class, not a fact about the business semantics. That a property is typically implemented as a field is a private detail of the class mechanics.
Properties aren't fields either, although they feel like them. They are actually a pair of methods (getter and setter) with special syntax.
Events are similarly a pair of methods (subscribe and unsubscribe) with special syntax.
In both cases, you usually have a private "backing field" inside your class, which holds the value manipulated by the getter/setter/subscribe/unsubscribe methods. And there's an auto-implemented syntax for both properties and events where the compiler generates the backing field and accessor methods for you.
The purpose is also the same: Properties provide restricted access to a field, where some validation logic is run before storing a new value. And an event provides restricted access to a delegate field, where consumers can only subscribe or unsubscribe, not read the list of subscribers, nor replace the whole list at once.
Let's consider the two ways to declare events.
Either you declare an event using an explicit add/remove method, or you declare an event without such methods.
In other words, you declare the event like this:
public event EventHandlerType EventName
{
add
{
// some code here
}
remove
{
// some code here
}
}
or you declare it like this:
public event EventHandlerType EventName;
The thing is, in some ways they're the same thing, and in other ways, they're completely different.
From the perspective of outside code, that is ... code outside of the class publishing the event, they're the exact same thing. To subscribe to an event, you call a method. To unsubscribe, you call a different method.
The difference is that in the second example code above, those methods will be provided by the compiler for you, however, that's still how it's going to be. To subscribe to the event, you call a method.
The syntax to do so, in C#, however, is the same, you do either:
objectInstance.EventName += ...;
or:
objectInstance.EventName -= ...;
So from the "outside perspective", the two ways are no different at all.
However, inside the class, there is a difference.
If you try to access the EventNameidentifier inside the class, you're actually referring to the field that backs the property, but only if you use the syntax that doesn't explicitly declare an add/remove method.
A typical pattern is like this:
public event EventHandlerType EventName;
protected void OnEventName()
{
var evt = EventName;
if (evt != null)
evt(this, EventArgs.Empty);
}
In this case, when you're referring to EventName, you're actually referring to the field that holds the delegate of type EventHandlerType.
However, if you've explicitly declared the add/remove methods, referring to the EventName identifier inside the class will be just like outside of the class, since the compiler cannot guarantee that it knows the field, or any other mechanism, in which you store the subscription.
An event is an accessor for a delegate. Just like a property is an accessor for a field. With the exact same utility, it prevents code from messing with the delegate object. Like a property has a get and set accessor, an event has the add and remove accessor.
It does behave somewhat different from a property, if you don't write the add and remove accessors yourself then the compiler auto-generates them. Including a private backing field that stores the delegate object. Similar to an automatic property.
You don't do this often but it is certainly not unusual. The .NET framework pretty commonly does so, for example the events of the Winforms controls are stored in an EventHandlerList and the add/remove accessors manipulate that list through its AddHandler() and RemoveHandler() methods. With the advantage that all the events (there are many) require only a single field in the class.
I can add to the former answers that delegates can be declared inside a namespace scope (outside a class) and events can be declared only inside a class.
This is because delegate is a class!
Another distinction is that , for events, the containing class is the only one that can fire it.
You can subscribe/unsubscribe to it via the containing class, but can't fire it (in contrast to delegates).
So maybe you can understand now why the convention is to wrap it inside a protected virtual OnSomething(object sender, EventArgs e). It is for the descendants to be able to override the implementation of the firing.

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.

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