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.
Object Sender is a parameter called Sender that contains a reference to the control/object that raised the event.
An event is declared using the event keyword. Delegate is a function pointer. It holds the reference of one or more methods at runtime. Delegate is independent and not dependent on events.
Delegates allow methods to be passed as parameters. Delegates can be used to define callback methods. Delegates can be chained together; for example, multiple methods can be called on a single event. Methods don't have to match the delegate type exactly.
C# delegates are similar to pointers to functions, in C or C++. A delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime. Delegates are especially used for implementing events and the call-back methods. All delegates are implicitly derived from the System.
Why? People always ask this. In this end, this 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. I think back to how bad it was with Win32—when data was in WPARAM versus LPARAM, and so on. The pattern becomes noise and developers just assume that event handlers have scope to the sender and arguments of the event.
-Chris Anderson, in Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
If you're a .NET developer and you haven't read that book, you're missing out. It gives you a window ;) into the minds of the Microsoft .NET Framework designers, and a lot of best practices (including the reasoning behind them).
(Plus, you can run FxCop to verify that these practices are being followed.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With