EventHandler type with no event args - c#

When we want to pass data to an event subscriber, we use EventArgs (or CustomEventArgs) for this.
.Net provides a build in type EventHandler that uses as a parameter an instance of EventArgs class that is build in as well.
What about cases, when I need to notify a subscriber that some action is over, for example search is over? I don't want to even use EventArgs, that won't contain anything.
Is there a build in type for signaling another class, without the need to use empty EventArgs?

I really would advise you to use the standard EventHandler pattern here and just pass EventArgs.Empty. However, you can use Action as an event type if you really want – it is just unusual.

You have several options:
Use a normal event with an EventHandler and the basic EventArg class – sure the event is empty, but does this do any harm?
Make your own delegate and use this with event MyDelegateWithoutParams MyEvent;
Use the Observer Pattern with IObservable instead.
Let clients pass an Action to you and call this action.
I hope one of these options is to your liking. I use 1 and 4 for this kind of situation (4 mostly, if there will be only one "listener").
PS: I guess 2 won't conform to the .NET framework guidelines, so maybe that one is not the best idea ;)

if you use plain delegates surely you can do what you want but if you use events I think the best is to stick on the standard and always have object sender and EventArgs e.
if you really do not know what to pass on firing those events from your own code, just pass EventArgs.Empty as second parameter.

Use Actions (below answer copied from https://stackoverflow.com/a/1689341/1288473):
Declaring:
public event Action EventWithoutParams;
public event Action<int> EventWithIntParam;
Calling:
EventWithoutParams?.Invoke();
EventWithIntParam?.Invoke(123);

Related

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 pass dummy object to Event Handler in 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!

Dictionary of events

Is there anything in c# that you can use to create a collection of events like lists, hashsets, and a dictionary in this case? Thankyou.
Sure you can:
Dictionary<String, Delegate> m_events = new Dictionary<String, Delegate>();
In Jeff Richter's Book CLR via C# you can find a complete implementation of an EventSet class.
(Even if you don't have the book you can download the sample code from https://www.wintellect.com/wp-content/uploads/2017/09/CLR-via-C-4th-Edition-Code.zip. The class in question is in "Ch11-1-EventSet.cs".)
As far as the question goes what an event is:
Say you have this line of code in your class:
public event EventHandler<NewMailEventArgs> NewMail;
then the C# compiler will translate the line above into three constructs:
A private delegate field. (Something like: private EventHandler<NewMailEventArgs> NewMail;
A public add_Xxx method (where Xxx is the Event name) that interested subscribers can use to register a callback delegate with the event.
A public remove_Xxx method (where Xxx is the Event name) that subscribers can use to unregister from the event.
(All the gory details can be found in section 11.2 of aforementioned book.)
So in other words the 'thing' you can store in your Event collection class is just a plain old delegate nothing else.
An event is like a property or method; you cant store instances of them. You can use reflection, but this likely isn't what you want.
Did you mean you want to store a list of methods to call when your event is fired? Events already do that.
EDIT:
Ah, I think I get it now. If you just simply fire your event, only the B instances that want it will get it. If you pass into the event args the instance of A that fired the event, then the B instance will be able to tell where it came from. But a B will never get an event from an A that it didn't ask for an event.
EDIT:
Maybe not. You only want to fire an event on one of the B's? Make B implement an interface that has a callback method. Instead of firing an event, call the method on the correct instance of B.
You could use IList with out any trouble. Type T could be any type defined in .net or user defined class.

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