Question

It's known that you should declare events that take as parameters (object sender, EventArgs args). Why?

Was it helpful?

Solution

This allows the consuming developer the ability to write a single event handler for multiple events, regardless of sender or event.

Edit: Why would you need a different pattern? You can inherit EventArgs to provide any amount of data, and changing the pattern is only going to serve to confuse and frustrate any developer that is forced to consume this new pattern.

OTHER TIPS

Actually this is debatable whether or not this is the best practice way to do events. There is the school of thought that as events are intended to decouple two segments of code, the fact that the event handler gets the sender, and has to know what type to cast the sender into in order to do anything with it is an anti-pattern.

Because it's a good pattern for any callback mechanism, regardless of language. You want to know who sent the event (the sender) and data that is pertinent to the event (EventArgs).

Using a single parameter, EventArgs, for the data passed by an event allows you to add data to your event in future versions of your software without breaking existing consumers. You simply add new members to an existing EventArgs-derived class, or create a derived class with the new members.

Otherwise consistency and the principle of least surprise justify using EventArgs for passing data.

As for sender, in some (but not all) cases it's useful to know what type sent the event. Using a type other than object for the sender argument is too restrictive: it would mean that other senders couldn't reuse the same event signature.

It is a good pattern to use, that way what ever implements the event can find what was sending it.

Also overriding the EventArgs and passing data through them is the best method. The EventArgs are a base class. If you look at various controls that call events, they have overridden EventArgs which gives you more information about the event.

Even if you don't need the arguments to do the event, if you do not include them with the first run of the framework and want to add them later, you break all previous implementations, and have to re-write them. Plus if you a creating a framework and going to distribute that it becomes worse because everybody that uses your framework will need to refactor.

Chris Anderson says in the Framework Design Guidelines book:

[T]his is just about a pattern. By having event arguments packaged in a class you get better versioning semantics. By having a common pattern (sender, e) it is easily learned as the signature for all events.

There are situations mostly involving interop that would require deviation from this pattern.

It seemed that this was Microsoft's way to evolve the event model over time. It also seems that they are also allowing another way to do it with the "new" Action delegate and it's variations.

"Object sender" allows to reuse one method for multiple objects when the handler method is supposed to do something with the object that raised the event, for example 3 textbox can have one single handler that will reset the text of the firing textbox.

EventArgs's main advantage is that it allows to refactor event information without the need to change signatures of all handlers in all projects that are subscribed to this kind of event.

I can't think of a smarter way to deal with events.

Sometimes you would like to force all of your event consumers to use a particular event parameter, for example, a security event which passes a boolean parameter, true for good, false for bad. In this case you want your consumer to be painfully aware of the new parameter, i.e. you want your consumers to be coupled with that parameter. Take note, your consumers are still decoupled from your event firing class, but not from your event.

I suspect that this scenario applies to a large number of cases and in those cases the value of EventArgs is greatly reduced.

The EventArgs class alone is useless since it must be derived to instantiate with any content. This would indicate a subclass should be used, and many already exist in .NET. Sadly, I can't find any good generic ones.

Let's say you want to delegate logging to a generic event... WITHOUT WRITING YOUR OWN EventArgs SUBCLASS. It may seem a pointless exercise, but I like using existing features. You can pass your string through the Object argument, but that goes against it's intended use. Try to find a good reference of EventArgs subclasses on Google, and you'll come up dry. (At least I did.)

ReSharper helps a bit, since when you type "EventArgs" you'll see a list of all classes (within your using/imports scope) that CONTAIN the string "EventArgs". Perusing the list you'll see many classes with no string members. When you get to ControlEventArgs, you see that the Text property might be used, but with all of the overhead of a windows control. ConvertEventArgs might be useful, since you pass the type along with the data, but this still requires tight coupling that's neither well-documented nor inherently type-safe. DataReceivedEventArgs has no implementation. EntryWrittenEventArgs requires an EventLogEntry with a byte array or StreamingContext for data. ErrorEventArgs is closer, with an Exception message, if you don't mind calling all of your log events Exception ErrorEvents internally. FileSystemEventArgs is probably the closest yet, with two strings and a required WatcherChangeTypes enum argument that CAN be set to 0, if you know what you're doing. LabelEditEventArgs uses an int and a string, if you don't mind requiring the Windows.Forms namespace. RenamedEventArgs is similar to FileSystemEventArgs with an extra string. Finally, ResolveEventArgs in System.Runtime.InteropServices passes a single string. There are other libraries, but I stuck to some of the most common ones. So, depending on the implementation I can use ErrorEventArgs, FileSystemEventArgs or ResolveEventArgs for logging.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top