I have the following classes
Child class:
public class ChildClass
{
...
private void EventHandler(...);
...
}
Parent class:
public class ParentClass
{
...
ChildClass child;
...
private void EventHandler(...);
...
}
Both of them have an event handlers on the same event.
The question is in which order those handlers will be called?
Important note
Servy has very correctly pointed out that we cannot rule out the possibility that the event in question is owned by a third party and it implements the accessors itself. If that is the case then all bets are off.
The original answer below silently assumes that we are talking about a bog-standard, totally uninteresting event implementation.
Original answer
Events are implemented through delegates.
From MSDN:
A useful property of delegate objects is that multiple objects can be
assigned to one delegate instance by using the + operator. The
multicast delegate contains a list of the assigned delegates. When the
multicast delegate is called, it invokes the delegates in the list, in
order.
So the handlers are invoked in the order that you add them to the event.
The order in which the delegates are subscribed to, although since it's not properly noted anywhere in the specification (that I know of) that this is expected behaviour, specifically, then relying on such order could be folly, as it could change per implementation.
it will be called int the order they are registered.
While the MSDN documentation clearly states that the multicast delegates invokes the delegates in the order in which they subscribed, that assumes that the subscription order is deterministic, i.e. that you are in a single-threaded environment.
If that is not the case, you may be better off defining two events: a BeforeEventOccurs event and an AfterEventOccurs event. This will give you deterministic control over the order even in a multi-threaded environment.
According to this question event handlers get called in the order they are subscribing to the event.
From Delegates
Delegates are used to pass methods as arguments to other methods.
Event handlers are nothing more than methods that are invoked through
delegates. You create a custom method, and a class such as a windows
control can call your method when a certain event occurs.
From How to: Combine Delegates (Multicast Delegates) page;
A useful property of delegate objects is that multiple objects can be
assigned to one delegate instance by using the + operator. The
multicast delegate contains a list of the assigned delegates. When the
multicast delegate is called, it invokes the delegates in the list, in
order.
Related
I've been recently learning 'events' and 'delegates' in C#.
Now I have a question that I didn't find the answer to, anywhere else.
As we all know every event is created based on a specific delegate. At first I thought that events are like delegate instances, but then I figured out that they are not.
My question here is that what is the relation between an event and its base delegate? does that event create an instance of the delegate and assign the 'event handler' methods to that at the runtime? or the assigned delegate is just a convention for assigning 'event handlers'?
An event is basically a list of methods to be invoked. Thus, delegate is nothing but kind of "strongly-typed" method reference. That is why there are exactly 2 possible operations on events: add handler += and remove handler: -=. That should prevent mistakes like accidental .Clear(), which will unsubscribe all existing listeners momentarily.
If you need more "obvious" example of how it works, than let the List<Delegate> be an event, where Delegate represents reference to a whatever function of a certain signature. Whenever you need to "invoke" event, you loop over existing list of delegates and simply invoke each one with the same parameter.
An event for a delegate is the same as aan auto-property for a backing-field. As an auto-property is just a wrapper around a backing-field an event is just a wrapper around a (backing) delegate. It provides an add- and a remove-method to append or remove event-handlers. So you have a private list of handlers and the event is just a wrapper to expose this list to the outside.
You can define an event as follows:
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent
{
add { _explicitEvent += value; }
remove { _explicitEvent -= value; }
}
So you have a private backing-field, which is a delegate. You can surely assign multiple handlers to the same delegate and thus to the event. In fact when you have an event as this:
public event EventHandler MyEvent;
the compiler will implicitely create the private backing-delegate for you, as it does for auto-properties also.
As for properties you can add some further logic within the add- and -remove-accessors in order to modify what happens when assigining an handler. You could make some validations for example or call some logging.
According to Microsoft Docs => Here
An event is a special kind of multicast delegate that can only be invoked from within the class that it is declared in. Client code subscribes to the event by providing a reference to a method that should be invoked when the event is fired. These methods are added to the delegate's invocation list through event accessors.
So, the answer would be: Yes. Events are basically a special type of multicast delegate.
For example, I understand that I can't pass an event to a method or a constructor, but I don't understand why I can't. What makes an event different then a collection of delegates?
... while events look like delegate instances in terms of the way you express the add and remove operations, they're not.
Events are pairs of methods, appropriately decorated in IL to tie them together and let languages know that the methods represent events. The methods correspond to add and remove operations, each of which take a delegate instance parameter of the same type (the type of the event). What you do with those operations is pretty much up to you, but the typical use is to add or remove the delegate from a list of handlers for the event.
From Jon Skeet's C# in Depth: Delegates and Events
An event is declared within a class to allow objects external to the class to be attach to the event and be notified about changes occurring within that class.
If it were a first-class citizen then the event could be invoked from an external class meaning that any rogue code with a reference to the event, of a Button say, could cause the Click event to be fired.
To prevent this events have special access rules that only allow the class that declares the event (and not even its own subclasses) to fire the event.
Hence, for this safety, events are not first-class citizens of the .NET Framework.
Interview question: Why can't events be invoked and their invocation list set from outside of the declaring class?
I found explanation to the first part of the question in this post Events Invocation
I assume the answer for the second part lies with security.
Are there any other reasons considerations?
A keyword your interviewer may be looking for is encapsulation.
Events are only supposed to expose subscribe and unsubscribe operations to potential subscribers. Invocation is really the responsibility of the class that exposes the event.
Also keep in mind that public event EventHandler FooBar; is a short form of the following syntax
private EventHandler _fooBar;
public event EventHandler FooBar
{
add
{
_fooBar = (EventHandler)Delegate.Combine(_fooBar, value);
}
remove
{
_fooBar = (EventHandler)Delegate.Remove(_fooBar, value);
}
}
See Event Accessors
Because the class is the owner of those events.
We say that example in OOPS should be taken from real world examples. So if you are an entity and you do an event of let's say raising your hand, would you like to keep the authority of raising your hand with yourself or give to someone else?
But there is a catch
A C# short-format event declaration direct the compiler to declare a field of delegate type which, for unfortunate historical reasons, is given the same name as the event. Because the field declaration is generated by the compiler, rather than being part of user code, there is no means by which its scope can be set to anything other than private. If you wish to have the delegate or delegates associated with an event be accessible to child classes, then it's necessary to use something like the form shown by Brandon Cuff (though perhaps guarded with an Interlocked.CompareExchange).
In C# in depth (an excellent book thus far), Skeet explains events aren't fields. I read this section many times and I don't understand why the distinction makes any difference.
I am one of those developers that confuse events and delegate instances. In my mind, they are the same. Aren't both just a form of indirection? We can multicast both. An event is setup as a field as shorthand...sure. But, we are adding or removing handlers. Stacking them up to be called when the event fires. Don't we do the same thing with delegates, stack them up and call invoke?
The other answers are basically correct, but here's another way to look at it:
I am one of those developers that confuse events and delegate instances. In my mind, they are the same.
An old saying about not seeing the forest for the trees comes to mind. The distinction that I make is that events are at a higher "semantic level" than a field of delegate instance. An event tells the consumer of the type "hi there, I am a type that likes to tell you when something happens". The type sources an event; that's part of its public contract.
How, as an implementation detail, that class chooses to keep track of who is interested in listening to that event, and what and when to tell the subscribers that the event is happening, is the business of the class. It happens to typically do so with a multicast delegate, but that's an implementation detail. It is such a common implementation detail that it is reasonable to confuse the two, but we really do have two different things: a public surface, and a private implementation detail.
Similarly, properties describe the semantics of an object: a customer has a name, so a Customer class has a Name property. You might say that "their name" is a property of a customer, but you would never say that "their name" is a field of a customer; that's an implementation detail of a particular class, not a fact about the business semantics. That a property is typically implemented as a field is a private detail of the class mechanics.
Properties aren't fields either, although they feel like them. They are actually a pair of methods (getter and setter) with special syntax.
Events are similarly a pair of methods (subscribe and unsubscribe) with special syntax.
In both cases, you usually have a private "backing field" inside your class, which holds the value manipulated by the getter/setter/subscribe/unsubscribe methods. And there's an auto-implemented syntax for both properties and events where the compiler generates the backing field and accessor methods for you.
The purpose is also the same: Properties provide restricted access to a field, where some validation logic is run before storing a new value. And an event provides restricted access to a delegate field, where consumers can only subscribe or unsubscribe, not read the list of subscribers, nor replace the whole list at once.
Let's consider the two ways to declare events.
Either you declare an event using an explicit add/remove method, or you declare an event without such methods.
In other words, you declare the event like this:
public event EventHandlerType EventName
{
add
{
// some code here
}
remove
{
// some code here
}
}
or you declare it like this:
public event EventHandlerType EventName;
The thing is, in some ways they're the same thing, and in other ways, they're completely different.
From the perspective of outside code, that is ... code outside of the class publishing the event, they're the exact same thing. To subscribe to an event, you call a method. To unsubscribe, you call a different method.
The difference is that in the second example code above, those methods will be provided by the compiler for you, however, that's still how it's going to be. To subscribe to the event, you call a method.
The syntax to do so, in C#, however, is the same, you do either:
objectInstance.EventName += ...;
or:
objectInstance.EventName -= ...;
So from the "outside perspective", the two ways are no different at all.
However, inside the class, there is a difference.
If you try to access the EventNameidentifier inside the class, you're actually referring to the field that backs the property, but only if you use the syntax that doesn't explicitly declare an add/remove method.
A typical pattern is like this:
public event EventHandlerType EventName;
protected void OnEventName()
{
var evt = EventName;
if (evt != null)
evt(this, EventArgs.Empty);
}
In this case, when you're referring to EventName, you're actually referring to the field that holds the delegate of type EventHandlerType.
However, if you've explicitly declared the add/remove methods, referring to the EventName identifier inside the class will be just like outside of the class, since the compiler cannot guarantee that it knows the field, or any other mechanism, in which you store the subscription.
An event is an accessor for a delegate. Just like a property is an accessor for a field. With the exact same utility, it prevents code from messing with the delegate object. Like a property has a get and set accessor, an event has the add and remove accessor.
It does behave somewhat different from a property, if you don't write the add and remove accessors yourself then the compiler auto-generates them. Including a private backing field that stores the delegate object. Similar to an automatic property.
You don't do this often but it is certainly not unusual. The .NET framework pretty commonly does so, for example the events of the Winforms controls are stored in an EventHandlerList and the add/remove accessors manipulate that list through its AddHandler() and RemoveHandler() methods. With the advantage that all the events (there are many) require only a single field in the class.
I can add to the former answers that delegates can be declared inside a namespace scope (outside a class) and events can be declared only inside a class.
This is because delegate is a class!
Another distinction is that , for events, the containing class is the only one that can fire it.
You can subscribe/unsubscribe to it via the containing class, but can't fire it (in contrast to delegates).
So maybe you can understand now why the convention is to wrap it inside a protected virtual OnSomething(object sender, EventArgs e). It is for the descendants to be able to override the implementation of the firing.
Possible Duplicate:
What is the difference between a delegate and events?
Possible Duplicate:
Difference between events and delegates and its respective applications
(copied from this duplicate)
When i have to raise an event i do this
public delegate void LogUserActivity(Guid orderGUID);
public event LogUserActivity ActivityLog;
even this works
public delegate void LogUserActivity(Guid orderGUID);
public LogUserActivity ActivityLog;
What is the difference between two of them
There are three things here:
Declaring a delegate type
Creating a public variable of a delegate type
Creating a public event of a delegate type
The variable is just a normal variable - anyone can read from it, assign to it etc. An event only exposes subscribe/unsubscribe abilities to the outside world. A field-like event as you've shown here effectively has a "default" subscribe/unsubscribe behaviour, stored in a field with the same name. Within the declaring class, you access the field; outside you access the event.
I have an article about events and delegates which explains in more detail.
EDIT: To answer the comment, you can easily initialize a field-like event with a "no-op" handler:
public event LogUserActivity ActivityLog = delegate{};
Events and public delegates differ in one big way that keeps me from using public delegates in most cases:
Event:
obj.ActivityLog = null; // invalid
Public Delegate:
obj.ActivityLog = null; // valid
This matters, because I only want the subscriber to add/remove themselves from the list in most cases. I don't want other objects unhooking events from other subscribers.
In cases where the delegate is less of an event and more of a callback, I tend to use public methods to do this and keep the public delegate from being exposed directly:
obj.RegisterActivityCallback(...)
An event is an abstraction over a delegate, just as a property is an abstraction over a field. And - just like a property - an event allows you to gain fine control over what happens when a handler is added/removed:
public event LogUserActivity ActivityLog
{
add { ... }
remove { ... }
}
Indeed, your event may not have a delegate backing it at all, just like a property may not necessarily have a field backing it.
In the first case you can assign multiple listeners to your ActivityLog event as in:
logger.ActivityLog += new LogUserActivity(Listener1);
logger.ActivityLog += new LogUserActivity(Listener2);
Both methods (Listener1 and Listener2) will be called when the event is fired. In the second case you are not creating an event but a delegate. In this case you can only assign one listener:
logger.ActivityLog = new LogUserActivity(Listener1);
In this case you do not fire an event but instead you call the delegate. An event is really just a chain of delegates that are called in turn.
to add to all the previous answers, An event IS a delegate, of a specific type. A delegate is a type that is designed to act as a "smart" function pointer, or, putting it another way, as a smart "wrapper" for a function pointer, that allows the compiler to intelligently decide at compile time whether the function(s) you are sticking into the delegate are consistent with the uses you are making of the delegate (consistency is based on the function signature).
An event is a delegate with a specific signature, specifically, one that does not return anything (returns void), and takes two parameters, a System.object, to hold a reference to whatever object triggered the event, and an instance of some type derived from System.EventArgs, to hold whatever other data the event needs to carry with it from the initialtor to the handler.