Why does MSDN recommend including object sender in delegate declarations?
I was reading this page and I noticed how it said this is standard guidelines:
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.
I can understand how having an object sender
could be useful in some circumstances, but I could see the exact opposite in others. For example,
What if a class handling the event should not have any knowledge about who fired it? Coupling, cohesion, and all of that.
In my case, I already have a reference to the object as a member variable. That is how I subscribe to the event. There will only ever be one instance of it so there's no reason to cast the sender object rather than just using the member variable.
In my program the sender object should not be known at all to the clients. It's hard to explain what I am doing but basically I have a class with an internal constructor within a library that is used by two other classes also within that library. My client classes are subscribing to events from those two classes but the events are originally invoked from this internal class that clients should not have any knowledge of.
It is confusing to clients of the event handler. Libraries should be simple to understand and in my case, there is no reason to ever use the sender variable. None. Then why include it?
That being said, why does Microsoft indicate that event handlers should follow these guidelines? Isn't it not always the best choice?
EDIT: Thanks for the replies everyone. I've decided to go with the majority and use EventHandler<T>
for all my events in this library.
I think the reason for the pattern is to enforce some consistency. The sender parameter allows re-use of a single handler for multiple publishers (buttons, tables).
To address your points:
1) simply don't use it. That is common and doesn't really hurt any good practice.
2) that's OK, again ignore the sender
3) is in total contradiction of what you said under 2) ...
And for the rest it is the same as 1). You could even consider passing null
as sender.
4) "then why include it" - there are other use cases that do require the sender.
But do note this is just a guideline for libraries confirming to the BCL.
Your case sounds more like a specific application (not a library) so feel free to use any parameter scheme you like. The compiler won't complain.
You are fighting against the wind, the .NET framework has certain design, rules and guidelines and when using it, if you want to use it correctly, you are supposed to follow those directions.
if you use raw delegates you have all the freedom you want but as stated above if you are declaring a delegate type for an event you should include sender
object and EventArgs
object as well (base or derived class).
if you break those rules, as I said a moment ago in my answer to your other question: Should I use EventArgs or a simple data type?, you could potentially end up in a situation where your code breaks.
Simplyfying at the maximum, when the framework invokes an OnClick event on a control, the .NET Framework does pass the sender and an EventArgs
instance... if the event would not comply, something could break.
if you want full freedom then use simple delegates but not events.
First of all, it's important to note that a guideline is not a law.
All hell (or the programmer equivalent) will not break lose if you don't follow the guidelines.
As such, feel free to change the signature of your events appropriately.
However, it is just as important to know why these guidelines were added to begin with, and one big part of the answer(s) to that question is versioning.
By having the following two parts, and only those two parts:
object
is as generic as can be from back then) EventArgs
then you are designing code that is more resilient to changes.
First of all, since you're not "allowed" to add or remove parameters, all future versions of your event will still have only sender
and e
.
Secondly, there's a second part to the guideline regarding the e
parameter. If you in a new version of your class library decides to change the signature of an event handler by changing the type of the e
parameter, you're supposed to make it more specific by descending from your current type, and passing the descendant instead.
The reason for this is that existing code that already handles your current (old) type will still work.
So the entire reasoning behind the guideline is to:
Now, if any of this is not a concern for your case, feel free to not follow the guideline.
In fact, you can make an event out of an Action
and it'll work just fine.