Creating events without EventArgs - c#

When creating an event, it is standard to send an EventArgs object as the second argument. However, often times the event may only need to send one piece of data, such as a string or int. As far as I know, you cannot really do anything with the base EventArgs class.
So is it really necessary to create an entire new class with one field just to send a simple string/int with an event?
Example
public delegate void JoinButtonEvent(object sender, string buttonId);
vs
public delegate void JoinButtonEvent(object sender, JoinButtonEventArgs e);
Where JoinButtonEventArgs is a class with field called buttonId.

No it's not necessary for your code to compile; but coding conventions wise its a good idea.
Sure you only care about one variable this time, but if you need another variable in the future you have to update all the old code to have an additional parameter instead of just adding another property to a central class when you need something new. (As events are not polymorphic, and can not be overridden like methods can be, to have different parameters for the same method name)

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);

C# Action/Delegate Style Question

What is considered better style for an event definition:
public event Action<object, double> OnNumberChanged;
or
public delegate void DNumberChanged(object sender, double number);
public event DNumberChanged OnNumberChanged;
The first takes less typing, but the delegate one gives names to the parameters. As I type this, I think number 2 is the winner, but I could be wrong.
Edit: A different (third) approach is the winner. Read below.
Neither 1 or 2. A third option is the winner
public event EventHandler<NumberChangedEventArgs> NumberChanged;
You're breaking a number of style guidelines for developing in C#, such as using a type for event args that doesn't extend EventArgs.
Yes, you can do it this way, as the compiler doesn't care. However, people reading your code will do a WTF.
Don't create a new type if you don't have to. I think this is better:
public event Action<object, double> OnNumberChanged;
The reason that the Action and Func delegate families exist is to serve this very purpose and reduce the need for new delegate type creation by developers.
Typically I stick to using an EventArgs derived class as the argument. It makes the code much more consistent.
I have a class:
public class ApplyClickedEventArgs : EventArgs
{
...
}
and a handler:
void cpy_ApplyClicked(object sender, ApplyClickedEventArgs e)
{
...
}
The declaration is:
public event EventHandler<ApplyClickedEventArgs> ApplyClicked;
As with all questions about coding style. Pick the one you prefer, or that your team prefers, and keep it consistent throughout the project. As long as everyone who needs to can read it efficiently you will be fine.
I think option 1 is better if I were to choose, but IIRC, the official guidelines for events state that your second parameter has to be a class with the name XxxEventArgs, and should have EventArgs up in its inheritance chain.

Categories

Resources