Why pass dummy object to Event Handler in C#? - c#

the following is a function that invokes the event and thus notifies all clients.
public static void OnEventXYZ(XYZEventArgs e)
{
if(EventXYZ!=null)
EventXYZ(new object(),e);
}
This is from a sample code.
What i want to know is "What is the significance of new object()?
is this a syntax followed or only for this situation?

Normally you pass this as the sender parameter of an event handler.
However, in this case, the event is static so you cannot use this. The person who wrote that sample chose to pass new object() instead. I think most people would pass null instead but that's really a matter of personnal preference.

That parameter is for the sender of the event. Normally, you would use this, but that will not work in the static context.

EventXYZ seems to have been written to expect a sender (typical with event handlers). In the case of the static "On"blahBlah event raiser, the sender isn't really dealt with clearly. As another responder posted, it seems to be an attempt to satisfy the sender property of the event args that are passed along to the handler.
A more correct implementation would likely either omit the sender from the EventArgs or allow the static "OnBlahBlah" method an argument that allows the caller to specify the sender.
The use of "new object()" in this case seems like confusing fluff, IMHO. But, then again, we don't technically know the signature of the constructor being used in this case... perhaps the first argument is meant to be "Some random object that will be used as the thing we can blame later when your hard drive gets formatted".. maybe a new, empty, meaningless object is perfect for this.
Another thing to look for is that you may consider rewriting the code to be this:
public static void OnEventXYZ(XYZEventArgs e)
{
var evt = EventXYZ;
if(evt != null)
evt(new object(),e);
}
.. In a nutshell, that is a typical "sender as first argument" pattern that you see in 99% of event args / event handlers. Better examples will probably make more sense.
You can also use ILSpy or Reflector to look at the thousands of event raisers/handlers in the .NET runtime to get better examples of how the common patterns are coded.
EDIT: BTW, it's unusual to see static OnEvent raisers... it's a little odd. Not technically correct, but it sure messes up the typical "'this' as sender" pattern.
Cheers!

Related

Is it possible to target an EventHandler in a lambda expression?

For a simple example, if I had some sort of button UI class, could I write a function that takes an expression that points to its Click event handler:
SomeMethod<SomeButtonClass>(button => button.Click);
I'm trying to eliminate some magic strings currently being used for a system to make events awaitable. The code in question is derived from a blog post by Frank Krueger (a worthwhile read, if you want some background).
public static Task<TEventArgs> GetEventAsync<TEventArgs>(this object eventSource, string eventName) where TEventArgs : EventArgs {
//...
Type type = eventSource.GetType();
EventInfo ev = type.GetEvent(eventName);
//...
}
While the specifics inside probably aren't important, the full method allows you to use an Event triggering as the completion source for a Task, making it easier to manage with await. For some class that raises an event, you can tie into a Task based on that event with a simple call.
Task<EventArgs> eventTask = someEventCausingObject.GetEventAsync<EventArgs>("SomeEventHandler");
// traditionally used as someEventCausingObject.SomeEventHandler += ...;
await eventTask;
// Proceed back here when SomeEventHandler event is raised.
I have been using this happily for a couple projects, but it has its drawbacks, one of the biggest being the use of hard-coded event name strings. This makes event name changes turn into runtime exceptions, and determining usage of the event is difficult.
I started trying to make a version that would allow the EventHandler to be passed in as part of an Expression with the goal of something like this:
await someEventCausingObject.GetEventAsync<EventCausingClass, EventArgs>(x => x.SomeEventHandler);
...with the corresponding method signature...
public static Task<TEventArgs> GetEventAsync<TSource, TEventArgs>(this TSource eventSource, Expression<Func<TSource, EventHandler>> eventHandlerExpression) where TEventArgs : EventArgs {
//...
}
Unfortunately, the lambda expression in the calling code causes a compile error:
Error CS0070: The event `SomeEventHandler' can only appear on the left hand side of += or -= when used outside of the type `EventCausingClass'.
This makes some sense given how event handlers are typically used, but I was hoping to find a better solution going forward than the pre-specified string name. It seems searches for combinations of "expression" and "eventhandler" all tend to be polluted with people describing lambda expressions for beginning += event handler assignment. I'm hoping I am missing something obvious here.
No, it is not possible to target an event. Basically event is not a real type member, but just C# syntax which produces add_EventName and remove_EventName methods pair.
You could try refer to these internal methods name, but it's not possible in C# - http://msdn.microsoft.com/en-us/library/z47a7kdw.aspx
There are many similar questions in SO, with the same answer NO - like this one from Jon Skeet https://stackoverflow.com/a/4756021/2170171
If you're real crazy, you can try something like
private static void Subscribe(Action addHandler)
{
var IL = addHandler.Method.GetMethodBody().GetILAsByteArray();
// Magic here, in which we understand ClassName and EventName
???
}
with usage like
Subscribe(() => new Button().Click += null);
You could try using Cecil http://www.mono-project.com/Cecil for analyzing IL, or implement your own logic as it should not be too hard for predictable line of code.
I don't think that it is good solution though, as it just replaces one headache (proper event naming) with another one (proper Subscribe calling). Though, it will help with rename stuff.

What's the standard to make an event that doesn't pass any information along?

I've got an event that literally just lets the user know something happened. They have to manually take action for that event, as no data is passed from it.
However, I'm not sure what would be more idiomatic:
public event Action MyEvent;
//clearly says no arguments
public event EventHandler MyEvent;
//uses the EventHandler class to no effect, but might be more idiomatic.
public event Action<object> MyEvent;
//just like the first but passes the sender if needed.
Which would be the standard way to do this?
The idiomatic approach would be to just use EventHandler. Pass in an appropriate sender if you have one or null otherwise, and EventArgs.Empty.
I know it's somewhat crazy, but that's the convention. Bear in mind that plain EventArgs has no useful information in it, so any EventHandler-based event is basically saying "I may get a sender, but that's probably all."
However, with delegate variance as of C# 2, there is a benefit to this: you can use the same event handling method for all events which follow the convention... so you can have (say) logging event handlers which use reflection to dump whatever information they are given in the EventArgs, even if they don't know about it at compile-time.
It's not the greatest argument in the world for a convention, admittedly - but it's a reasonably strong one. Of course routed events are slightly different in how they're subscribed, but even so the delegates follow the same pattern.

why do we need delegates [duplicate]

I'm looking to implement the Observer pattern in VB.NET or C# or some other first-class .NET language. I've heard that delegates can be used for this, but can't figure out why they would be preferred over plain old interfaces implemented on observers. So,
Why should I use delegates instead of defining my own interfaces and passing around references to objects implementing them?
Why might I want to avoid using delegates, and go with good ol'-fashioned interfaces?
When you can directly call a method, you don't need a delegate.
A delegate is useful when the code calling the method doesn't know/care what the method it's calling is -- for example, you might invoke a long-running task and pass it a delegate to a callback method that the task can use to send notifications about its status.
Here is a (very silly) code sample:
enum TaskStatus
{
Started,
StillProcessing,
Finished
}
delegate void CallbackDelegate(Task t, TaskStatus status);
class Task
{
public void Start(CallbackDelegate callback)
{
callback(this, TaskStatus.Started);
// calculate PI to 1 billion digits
for (...)
{
callback(this, TaskStatus.StillProcessing);
}
callback(this, TaskStatus.Finished);
}
}
class Program
{
static void Main(string[] args)
{
Task t = new Task();
t.Start(new CallbackDelegate(MyCallbackMethod));
}
static void MyCallbackMethod(Task t, TaskStatus status)
{
Console.WriteLine("The task status is {0}", status);
}
}
As you can see, the Task class doesn't know or care that -- in this case -- the delegate is to a method that prints the status of the task to the console. The method could equally well send the status over a network connection to another computer. Etc.
You're an O/S, and I'm an application. I want to tell you to call one of my methods when you detect something happening. To do that, I pass you a delegate to the method of mine which I want you to call. I don't call that method of mine myself, because I want you to call it when you detect the something. You don't call my method directly because you don't know (at your compile-time) that the method exists (I wasn't even written when you were built); instead, you call whichever method is specified by the delegate which you receive at run-time.
Well technically, you don't have to use delegates (except when using event handlers, then it's required). You can get by without them. Really, they are just another tool in the tool box.
The first thing that comes to mind about using them is Inversion Of Control. Any time you want to control how a function behaves from outside of it, the easiest way to do it is to place a delegate as a parameter, and have it execute the delegate.
You're not thinking like a programmer.
The question is, Why would you call a function directly when you could call a delegate?
A famous aphorism of David Wheeler
goes: All problems in computer science
can be solved by another level of
indirection.
I'm being a bit tongue-in-cheek. Obviously, you will call functions directly most of the time, especially within a module. But delegates are useful when a function needs to be invoked in a context where the containing object is not available (or relevant), such as event callbacks.
There are two places that you could use delegates in the Observer pattern. Since I am not sure which one you are referring to, I will try to answer both.
The first is to use delegates in the subject instead of a list of IObservers. This approach seems a lot cleaner at handling multicasting since you basically have
private delegate void UpdateHandler(string message);
private UpdateHandler Update;
public void Register(IObserver observer)
{
Update+=observer.Update;
}
public void Unregister(IObserver observer)
{
Update-=observer.Update;
}
public void Notify(string message)
{
Update(message);
}
instead of
public Subject()
{
observers = new List<IObserver>();
}
public void Register(IObserver observer)
{
observers.Add(observer);
}
public void Unregister(IObserver observer)
{
observers.Remove(observer);
}
public void Notify(string message)
{
// call update method for every observer
foreach (IObserver observer in observers)
{
observer.Update(message);
}
}
Unless you need to do something special and require a reference to the entire IObserver object, I would think the delegates would be cleaner.
The second case is to use pass delegates instead of IObervers for example
public delegate void UpdateHandler(string message);
private UpdateHandler Update;
public void Register(UpdateHandler observerRoutine)
{
Update+=observerRoutine;
}
public void Unregister(UpdateHandler observerRoutine)
{
Update-=observerRoutine;
}
public void Notify(string message)
{
Update(message);
}
With this, Observers don't need to implement an interface. You could even pass in a lambda expression. This changes in the level of control is pretty much the difference. Whether this is good or bad is up to you.
A delegate is, in effect, passing around a reference to a method, not an object... An Interface is a reference to a subset of the methods implemented by an object...
If, in some component of your application, you need access to more than one method of an object, then define an interface representing that subset of the objects' methods, and assign and implement that interface on all classes you might need to pass to this component... Then pass the instances of these classes by that interface instead of by their concrete class..
If, otoh, in some method, or component, all you need is one of several methods, which can be in any number of different classes, but all have the same signature, then you need to use a delegate.
I'm repeating an answer I gave to this question.
I've always like the Radio Station metaphor.
When a radio station wants to broadcast something, it just sends it out. It doesn't need to know if there is actually anybody out there listening. Your radio is able to register itself with the radio station (by tuning in with the dial), and all radio station broadcasts (events in our little metaphor) are received by the radio who translates them into sound.
Without this registration (or event) mechanism. The radio station would have to contact each and every radio in turn and ask if it wanted the broadcast, if your radio said yes, then send the signal to it directly.
Your code may follow a very similar paradigm, where one class performs an action, but that class may not know, or may not want to know who will care about, or act on that action taking place. So it provides a way for any object to register or unregister itself for notification that the action has taken place.
Delegates are strong typing for function/method interfaces.
If your language takes the position that there should be strong typing, and that it has first-class functions (both of which C# does), then it would be inconsistent to not have delegates.
Consider any method that takes a delegate. If you didn't have a delegate, how would you pass something to it? And how would the the callee have any guarantees about its type?
I've heard some "events evangelists" talk about this and they say that as more decoupled events are, the better it is.
Preferably, the event source should never know about the event listeners and the event listener should never care about who originated the event. This is not how things are today because in the event listener you normally receive the source object of the event.
With this said, delegates are the perfect tool for this job. They allow decoupling between event source and event observer because the event source doesn't need to keep a list of all observer objects. It only keeps a list of "function pointers" (delegates) of the observers.
Because of this, I think this is a great advantage over Interfaces.
Look at it the other way. What advantage would using a custom interface have over using the standard way that is supported by the language in both syntax and library?
Granted, there are cases where it a custom-tailored solution might have advantages, and in such cases you should use it. In all other cases, use the most canonical solution available. It's less work, more intuitive (because it's what users expect), has more support from tools (including the IDE) and chances are, the compiler treats them differently, resulting in more efficient code.
Don't reinvent the wheel (unless the current version is broken).
Actually there was an interesting back-and-forth between Sun and Microsoft about delegates. While Sun made a fairly strong stance against delegates, I feel that Microsoft made an even stronger point for using delegates. Here are the posts:
http://java.sun.com/docs/white/delegates.html
http://msdn.microsoft.com/en-us/vjsharp/bb188664.aspx
I think you'll find these interesting reading...
i think it is more related to syntatic sugar and a way to organize your code, a good use would be to handle several methods related to a common context which ones belong to a object or a static class.
it is not that you are forced to use them, you can programme sth with and without them, but maybe using them or not might affect how organized, readable and why not cool the code would be, maybe bum some lines in your code.
Every example given here is a good one where you could implement them, as someone said it, is just another feature in the language you can play with.
greetings
Here is something that i can write down as a reason of using delegate.
The following code is written in C# And please follow the comments.
public delegate string TestDelegate();
protected void Page_Load(object sender, EventArgs e)
{
TestDelegate TD1 = new TestDelegate(DiaplayMethodD1);
TestDelegate TD2 = new TestDelegate(DiaplayMethodD2);
TD2 = TD1 + TD2; // Make TD2 as multi-cast delegate
lblDisplay.Text = TD1(); // invoke delegate
lblAnotherDisplay.Text = TD2();
// Note: Using a delegate allows the programmer to encapsulate a reference
// to a method inside a delegate object. Its like the function pointer
// in C or C++.
}
//the Signature has to be same.
public string DiaplayMethodD1()
{
//lblDisplay.Text = "Multi-Cast Delegate on EXECUTION"; // Enable on multi-cast
return "This is returned from the first method of delegate explanation";
}
// The Method can be static also
public static string DiaplayMethodD2()
{
return " Extra words from second method";
}
Best Regards,
Pritom Nandy,
Bangladesh
Here is an example that might help.
There is an application that uses a large set of data. A feature is needed that allows the data to be filtered. 6 different filters can be specified.
The immediate thought is to create 6 different methods that each return the data filtered. For example
public Data FilterByAge(int age)
public Data FilterBySize(int size)
.... and so on.
This is fine but is a very limited and produces rubbish code because it's closed for expansion.
A better way is to have a single Filter method and to pass information on how the data should be filtered. This is where a delegate can be used. The delegate is a function that can be applied to the data in order to filter it.
public Data Filter(Action filter)
then the code to use this becomes
Filter(data => data.age > 30);
Filter(data => data.size = 19);
The code data => blah blah becomes a delegate. The code becomes much more flexible and remains open.

In a C# event handler, why must the "sender" parameter be an object?

According to Microsoft event naming guidelines, the sender parameter in a C# event handler "is always of type object, even if it is possible to use a more specific type".
This leads to lots of event handling code like:
RepeaterItem item = sender as RepeaterItem;
if (item != null) { /* Do some stuff */ }
Why does the convention advise against declaring an event handler with a more specific type?
MyType
{
public event MyEventHander MyEvent;
}
...
delegate void MyEventHander(MyType sender, MyEventArgs e);
Am I missing a gotcha?
For posterity: I agree with the general sentiment in the answers that the convention is to use object (and to pass data via the EventArgs) even when it is possible to use a more specific type, and in real-world programming it is important to follow the convention.
Edit: bait for search: RSPEC-3906 rule "Event Handlers should have the correct signature"
Well, it's a pattern rather than a rule. It does mean that one component can forward on an event from another, keeping the original sender even if it's not the normal type raising the event.
I agree it's a bit strange - but it's probably worth sticking to the convention just for familiarity's sake. (Familiarity for other developers, that is.) I've never been particularly keen on EventArgs myself (given that on its own it conveys no information) but that's another topic. (At least we've got EventHandler<TEventArgs> now - although it would help if there were also an EventArgs<TContent> for the common situation where you just need a single value to be propagated.)
EDIT: It does make the delegate more general purpose, of course - a single delegate type can be reused across multiple events. I'm not sure I buy that as a particularly good reason - particularly in the light of generics - but I guess it's something...
I think there's a good reason for this convention.
Let's take (and expand on) #erikkallen's example:
void SomethingChanged(object sender, EventArgs e) {
EnableControls();
}
...
MyRadioButton.Click += SomethingChanged;
MyCheckbox.Click += SomethingChanged;
MyDropDown.SelectionChanged += SomethingChanged;
...
This is possible (and has been since .Net 1, before generics) because covariance is supported.
Your question makes total sense if you're going top-down - i.e. you need the event in your code, so you add it to your control.
However the convention is to make it easier when writing the components in the first place. You know that for any event the basic pattern (object sender, EventArgs e) will work.
When you add the event you don't know how it will be used, and you don't want to arbitrarily constrain the developers using your component.
Your example of a generic, strongly typed event makes good sense in your code, but won't fit with other components written by other developers. For instance if they want to use your component with those above:
//this won't work
GallowayClass.Changed += SomethingChanged;
In this example the additional type-constraint is just creating pain for the remote developer. They now have to create a new delegate just for your component. If they're using a load of your components they might need a delegate for each one.
I reckon the convention is worth following for anything external or that you expect to be used outside of a close nit team.
I like the idea of the generic event args - I already use something similar.
I use the following delegate when I would prefer a strongly-typed sender.
/// <summary>
/// Delegate used to handle events with a strongly-typed sender.
/// </summary>
/// <typeparam name="TSender">The type of the sender.</typeparam>
/// <typeparam name="TArgs">The type of the event arguments.</typeparam>
/// <param name="sender">The control where the event originated.</param>
/// <param name="e">Any event arguments.</param>
public delegate void EventHandler<TSender, TArgs>(TSender sender, TArgs e) where TArgs : EventArgs;
This can be used in the following manner:
public event EventHandler<TypeOfSender, TypeOfEventArguments> CustomEvent;
Generics and history would play a big part, especially with the number of controls (etc) that expose similar events. Without generics, you would end up with a lot of events exposing Control, which is largely useless:
you still have to cast to do anything useful (except maybe a reference check, which you can do just as well with object)
you can't re-use the events on non-controls
If we consider generics, then again all is well, but you then start getting into issues with inheritance; if class B : A, then should events on A be EventHandler<A, ...>, and events on B be EventHandler<B, ...>? Again, very confusing, hard for tooling, and a bit messy in terms of language.
Until there is a better option that covers all of these, object works; events are almost always on class instances, so there is no boxing etc - just a cast. And casting isn't very slow.
I guess that's because you should be able to do something like
void SomethingChanged(object sender, EventArgs e) {
EnableControls();
}
...
MyRadioButton.Click += SomethingChanged;
MyCheckbox.Click += SomethingChanged;
...
Why do you do the safe cast in your code? If you know that you only use the function as an event handler for the repeater, you know that the argument is always of the correct type and you can use a throwing cast instead, e.g. (Repeater)sender instead of (sender as Repeater).
No good reason at all, now there's covarience and contravarience I think it's fine to use a strongly typed Sender. See discussion in this question
Conventions exist only to impose consistency.
You CAN strongly type your event handlers if you wish, but ask yourself if doing so would provide any technical advantage?
You should consider that event handlers don't always need to cast the sender... most of the event handling code I've seen in actual practice don't make use of the sender parameter. It is there IF it is needed, but quite often it isn't.
I often see cases where different events on different objects will share a single common event handler, which works because that event handler isn't concerned with who the sender was.
If those delegates were strongly typed, even with clever use of generics, it would be VERY difficult to share an event handler like that. In fact, by strongly typing it you are imposing the assumption that the handlers should care what the sender is, when that isn't the practical reality.
I guess what you should be asking is why WOULD you strongly type the event handling delegates? By doing so would you be adding any significant functional advantages? Are you making the usage more "consistent"? Or are you just imposing assumptions and constraints just for the sake of strong-typing?
You say:
This leads to lots of event handling
code like:-
RepeaterItem item = sender as RepeaterItem
if (RepeaterItem != null) { /* Do some stuff */ }
Is it really lots of code?
I'd advise never to use the sender parameter to an event handler. As you've noticed, it's not statically typed. It's not necessarily the direct sender of the event, because sometimes an event is forwarded. So the same event handler may not even get the same sender object type every time it is fired. It's an unnecessary form of implicit coupling.
When you enlist with an event, at that point you must know what object the event is on, and that is what you're most likely to be interested in:
someControl.Exploded += (s, e) => someControl.RepairWindows();
And anything else specific to the event ought to be in the EventArgs-derived second parameter.
Basically the sender parameter is a bit of historical noise, best avoided.
I asked a similar question here.
It's because you can never be sure who fired the event. There is no way to restrict which types are allowed to fire a certain event.
The pattern of using EventHandler(object sender, EventArgs e) is meant to provide for all events the means of identifying the event source (sender), and providing a container for all the event's specific payload.
The advantage of this pattern is also that it allows to generate a number of different events using the same type of delegate.
As for the arguments of this default delegate...
The advantage of having a single bag for all the state you want to pass along with the event is fairly obvious, especially if there are many elements in that state.
Using object instead of a strong type allows to pass the event along, possibly to assemblies that do not have a reference to your type (in which case you may argue that they won't be able to use the sender anyway, but that's another story - they can still get the event).
In my own experience, I agree with Stephen Redd, very often the sender is not used. The only cases I've needed to identify the sender is in the case of UI handlers, with many controls sharing the same event handler (to avoid duplicating code).
I depart from his position, however, in that I see no problem defining strongly typed delegates, and generating events with strongly typed signatures, in the case where I know that the handler will never care who the sender is (indeed, often it should not have any scope into that type), and I do not want the inconvenience of stuffing state into a bag (EventArg subclass or generic) and unpacking it. If I only have 1 or 2 elements in my state, I'm OK generating that signature.
It's a matter of convenience for me: strong typing means the compiler keeps me on my toes, and it reduces the kind of branching like
Foo foo = sender as Foo;
if (foo !=null) { ... }
which does make the code look better :)
This being said, it is just my opinion. I've deviated often from the recommended pattern for events, and I have not suffered any for it. It is important to always be clear about why it is OK to deviate from it.
Good question!
.
Well, that's a good question. I think because any other type could use your delegate to declare an event, so you can't be sure that the type of the sender is really "MyType".
I tend to use a specific delegate type for each event (or a small group of similar events). The useless sender and eventargs simply clutter the api and distract from the actually relevant bits of information. Being able to "forward" events across classes isn't something I've yet to find useful - and if you're forwarding events like that, to an event handler that represents a different type of event, then being forced to wrap the event yourself and provide the appropriate parameters is little effort. Also, the forwarder tends to have a better idea of how to "convert" the event parameters than the final receiver.
In short, unless there's some pressing interop reason, dump the useless, confusing parameters.

What would I lose by abandoning the standard EventHandler pattern in .NET?

There's a standard pattern for events in .NET - they use a delegate type that takes a plain object called sender and then the actual "payload" in a second parameter, which should be derived from EventArgs.
The rationale for the second parameter being derived from EventArgs seems pretty clear (see the .NET Framework Standard Library Annotated Reference). It is intended to ensure binary compatibility between event sinks and sources as the software evolves. For every event, even if it only has one argument, we derive a custom event arguments class that has a single property containing that argument, so that way we retain the ability to add more properties to the payload in future versions without breaking existing client code. Very important in an ecosystem of independently-developed components.
But I find that the same goes for zero arguments. This means that if I have an event that has no arguments in my first version, and I write:
public event EventHandler Click;
... then I'm doing it wrong. If I change the delegate type in the future to a new class as its payload:
public class ClickEventArgs : EventArgs { ...
... I will break binary compatibility with my clients. The client ends up bound to a specific overload of an internal method add_Click that takes EventHandler, and if I change the delegate type then they can't find that overload, so there's a MissingMethodException.
Okay, so what if I use the handy generic version?
public EventHandler<EventArgs> Click;
No, still wrong, because an EventHandler<ClickEventArgs> is not an EventHandler<EventArgs>.
So to get the benefit of EventArgs, you have to derive from it, rather than using it directly as is. If you don't, you may as well not be using it (it seems to me).
Then there's the first argument, sender. It seems to me like a recipe for unholy coupling. An event firing is essentially a function call. Should the function, generally speaking, have the ability to dig back through the stack and find out who the caller was, and adjust its behaviour accordingly? Should we mandate that interfaces should look like this?
public interface IFoo
{
void Bar(object caller, int actualArg1, ...);
}
After all, the implementor of Bar might want to know who the caller was, so they can query for additional information! I hope you're puking by now. Why should it be any different for events?
So even if I am prepared to take the pain of making a standalone EventArgs-derived class for every event I declare, just to make it worth my while using EventArgs at all, I definitely would prefer to drop the object sender argument.
Visual Studio's autocompletion feature doesn't seem to care what delegate you use for an event - you can type += [hit Space, Return] and it writes a handler method for you that matches whatever delegate it happens to be.
So what value would I lose by deviating from the standard pattern?
As a bonus question, will C#/CLR 4.0 do anything to change this, perhaps via contravariance in delegates? I attempted to investigate this but hit another problem. I originally included this aspect of the question in that other question, but it caused confusion there. And it seems a bit much to split this up into a total of three questions...
Update:
Turns out I was right to wonder about the effects of contravariance on this whole issue!
As noted elsewhere, the new compiler rules leave a hole in the type system that blows up at runtime. The hole has effectively been plugged by defining EventHandler<T> differently to Action<T>.
So for events, to avoid that type hole you should not use Action<T>. That doesn't mean you have to use EventHandler<TEventArgs>; it just means that if you use a generic delegate type, don't pick one that is enabled for contravariance.
Nothing, you lose nothing. I've been using Action<> since .NET 3.5 came out and it is far more natural and easier to program against.
I don't even deal with the EventHandler type for generated event handlers anymore, simply write the method signature you want and wire it up with a lambda:
btnCompleteOrder.OnClick += (o,e) => _presenter.CompleteOrder();
I don't like the event-handler pattern either. To my mind, the Sender object isn't really all that helpful. In cases where an event is saying something happened to some object (e.g. a change notification) it would be more helpful to have the information in the EventArgs. The only use I could kinda-sorta see for Sender would be to unsubscribe from an event, but it's not always clear what event one should unsubscribe to.
Incidentally, if I had my druthers, an Event wouldn't be an AddHandler method and a RemoveHandler method; it would just be an AddHandler method which would return a MethodInvoker that could be used for unsubscription. Rather than a Sender argument, I'd have the first argument be a copy of the MethodInvoker required for unsubscription (in case an object finds itself receiving events to which the unsubscribe invoker has been lost). The standard MulticastDelegate wouldn't be suitable for dispatching events (since each subscriber should receive a different unsubscription delegate) but unsubscribing events wouldn't require a linear search through an invocation list.

Categories