Dictionary of events - c#

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.

Related

How to invoke a delegate object

Hi I'm new to C# and currently working on an app using some 3rd party APIs. I came across two lines of code which appreciate it if you could help. Below is the code similar to the actual sample code I have
bank.Account.NewAcc += delegate (Customer customerInfo) {
Console.WriteLine ("Customer Name : " + customerInfo.Name);
};
The bank.Account.NewAcc is an event while Customer is a class.
Below are the questions:
Can we create a delegate of object and not method?
How can I invoke it? I don't have any other information provided by the APIs
Thank you very much.
Please find below the answers to your questions as per my knowldege:
1. Can we create a delegate of object and not method?
No. You can't. Because delegates mean Function Pointer. They can hold the reference of functions only. And the method's signature must match with the signature of the delegate.
2. How can I invoke it? I don't have any other information provided from the APIs
The delegate which is associated with an event as an event handler can be invoked in two ways. First, when the event will be raised, second, when you invoke event programmatically.
In your sample code, an anonymous delegate with a single parameter of type CustomerInfo has been bound to an event named NewAcc.
Once the NewAcc event is fired, the bound delegates would be executed, the code to fire \ raise the event could be like this:
public Class BankAccount { .....
protected virtual void OnNewAcc(CustomerInfo customerInfo)
{
CustomerEventHandler handler = NewAcc;
if (handler != null)
{
handler(this, customerInfo);
}
}
public event CustomerEventHandler NewAcc;
.... }
I hope this answered your question.
I am not quite sure what you mean by a delegate of "object". I doubt you can though. Delegates represent a list of methods to be called. You can't just assign any object value to it.
You don't invoke (or raise) events. The API does. Judging from the name of NewAcc, I guess the event will be raised when a new account is created. Try doing that to bank.Account. You might see the customer info getting printed. Obviously, this won't work 100%. You have to look inside bank.Account to know exactly when the event will be raised (or just ask the person who wrote it).
Note that the delegate can be written with a lambda expression:
bank.Account.NewAcc += (customerInfo) => Console.WriteLine ("Customer Name : " + customerInfo.Name);

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.

EventHandler type with no event args

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);

How to decide between a method or event?

I read a question ages ago "How do C# Events work behind the scenes?" and Jon answered that all events are similar to methods...
In a purely hypothetical situation, I was wondering if someone could explain or point me to a resource that says when to use an event over a method?
Basically, If I want to have a big red/green status picture which is linked to a Bool field, and I wanted to change it based on the value of the bool, should I:
a) Have a method called Changepicture which is linked to the field and changes the state of the bool and the picture.
b) Have a get/set part to the field and stick an event in the set part.
c) Have a get/set part to the field and stick a method in the set part.
d) Other?
To gain more information about events see this post.
You have options.
If your object already implements INotifyPropertyChanged and your red/green picture is a control which supports databinding, then you can simply fire the NotifyPropertyCHanged event on the bool's set method, and add a databinding on that property to your control.
If not implementing INotifyPropertyChanged, I would still recommend doing something similar. I.e. creating your own event handler, and having the reg/green picture subscribe to the event. Just straight up calling a method from the set of your property creates a tight coupling, which is generally a bad thing to do.
The answer is: It depends.
If your boolean value is in the codebehind class of your visual component (e.g. WinForm) you can call a method ChangePicture without doing strange things. But if your boolean value is architectural more far away from the visual component an event is the right way to handle the scenario because you can not easily call a method on the visual component because the class that contains the boolean value perhaps doesn´t even know your visual component exists. :)
The best way to figure out what you should do is to look at classes in the .NET framework and see how they are designed.
Methods are "doers" or "actions", while you can see events as notification mechanisms. That is if others could be interested is being notified when something happens in an object then you can surface an event and have one or more subscribers to these events.
Since events in .NET are multi-cast, meaning multiple objects can subscribe and therefore be notified of an event happening, that may be other reason to raise an event in your objects. Events also follow the observer pattern in that the subject (your class) is really unaware of the subscribers (loosely coupled). While in order to call a method, the secondary object needs to have a reference to an instance of your class.
Note that, a method in your class eventually raises and event. So let's say you have a method in your class called ChangePicture. Then in the method's implementation, you could eventually raise an event PictureChanged. if someone is interested in being notified of this event, they can subscribe to this event. This someone is typically not the one that made the method call to change the picture.
Events are delegates. Delegates are objects. Event's are actually MulticastDelegates (a base class in the .NET framework). These objects eventually call a method, which is the method that gets called as part of the event notification. So they are slightly "heavier" then just a method call, but that should almost never determine your design.

Why can I check some event handlers for null, some not?

I have a ugly piece of code that adds event handlers. The problem is, if the code is called multiple times, the event handlers are called multiple times.
To solve the problem, I remove the event handler first and then add it.
Now I've seen the following behaviour:
Some event handlers can be checked like:
if (object.event == null) {
//
// Code
//
}
others of the form
if (object.object.event == null) {
//
// Code
//
}
I get a message like 'object.object.event' may only occur left of -= or +=.
(Since I'm using a german version of visual studio, I don't know the correct translation to english).
I have no idea why the behaviour looks this inconsequent so I would be grateful for some information on this.
To be more specific: It's user control.
if (myControl.Event == null) {
//
// works
//
}
if (myControl.TreeView.NodeMouseClick == null) {
//
// doesn't work
//
}
To solve the problem, I remove the event handler first and then add it.
That doesn't solve the problem. The event keyword provides accessors for a delegate object. Much like a property provides accessors for a field. On a property, you always need one get or set. An event has the add, remove and raise accessors. But the compiler will generate a default implementation for them if you don't do so yourself. Which is fairly common.
The advantage of a property accessor is that the backing field can be private. Nobody can mess with it, except the class that contains the field. All access has to go through the get and set accessors. The event keyword works exactly the same way, nobody can mess with the delegate object, except the code in the class that contains the event.
Which shoots a gaping hole in your attempt to avoid raising the event. You cannot mess with the list of subscribers for an event that's declared in another class, the compiler is telling you this. The normal way this is done is setting a bool flag to indicate that events have to be temporarily ignored. The event handler can check that flag and avoid executing any side-effects.
SLaks is correct, and has linked to some excellent resources. Here's a relevant quote from Chris Burrows' blog article:
Let me take a quick detour here and explain to you how the binding of += works in C#. There are two possibilities:
either there is an actual + operator, such as with ints, and x += y binds to “x = x + y” except that x is only evaluated once. This is the compound assignment operator; or
the thing on the left hand side is an event, and x.E += y binds to “x.add_E(y)”. This is the event accessor operator, and in fact this is the only way to bind to an event accessor.
So what do we have in the snippet above? Well, the extra bit of detail that you need to decide is the following rule about field-like events in C#: outside of the class or struct that defines a field-like event E, binding to the name E resolves to the event itself, on which the only legal operation is calling an accessor; inside the class or struct that defines a field-like event E, binding to the name E resolves to the private delegate field.
In your case, when resolving myControl.Event, you're inside the myControl class, so you don't see an event object; instead you see an actual delegate object, which you can compare with null. When resolving myControl.TreeView.NodeMouseClick, you're outside the TreeView class, so you can't access the actual delegate object; all you get is the event object, which cannot be compared to null.
If I understand correctly, all of this wouldn't help you anyway, since presumably after you check for null, you're going to try to fire the TreeView's event for it, which you can't do.
Depending on what you're trying to do, you could probably subclass TreeView and add an internal method that would call the protected TreeView.OnNodeMouseClick method to fire the event.
You can only access the backing field for an event defined in your class.
For more information, see the spec. (Although this has changed in C# 4, the changes are irrelevant to you)
Best practice in your case would be to create a protected internal OnEventName method in each class.
You can only query your own eventhandlers for attached listeners.
Automatic events, like this one:
public event EventHandler SomethingHappened;
are implemented by the compiler using a multicast delegate.
When you write myControl.Event == null, the compiler actually needs to call Delegate.GetInvocationList on that delegate. The compiler does not let you do that unless the code is inside a method of the class exposing the event, hence the error (it only allows you to add or remove from the invocation list).
If we were talking about an event you define in your own class, then you would have the option of exposing the invocation list (e.g. through a method) and doing what you are trying to do. But for existing classes (e.g. TreeView) it is not possible.

Categories