Events aren't fields - I don't get it - c#

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.

Related

Why is an event not a first class object in C#

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.

Why can't events be invoked or their invocation list set from outside of the declaring class

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

C# events and class hierachy

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.

Packing event arguments in a class, why?

Most .NET stock events are have this signature:
delegate void SomethingSomething(SomethingEventArgs e);
event SomethingSomething OnSomethingSomething;
and
class SomethingEventArgs
{
public string Name;
public int Index;
public double Groar;
}
Why is that better (obviously is, otherwise anyone would choose to do) than:
delegate void SomethingSomething(string Name, int Index, double Groar);
event SomethingSomething OnSomethingSomething;
since you don't have to pack your parameters to an object, and without initializers (.NET 2.0) it was kind of typing exercise.
One reason that comes to mind is that you can return your values simpler when having them packed in an object - ie. handler can modify a member of the object. However, with multicast events, that can't always be good anyway.
So, why?
Read about Open/Closed principle.
By using a class, all inherited classes can introduce extra functionality without having to change the delegate signature. They can simply introduce a new event class (ExtendedEventArgs) which inherits yours (SomeEventArgs).
The main reason is that it is more maintainable. If you pass an objects and any of the properties change, you only have to modify that. If you pass variables, that is a lot more work. So, the code gets more maintainable and more readable this way.
A quote from Microsoft's Code Complete:
Limit the number of a routine’s parameters to about seven. Seven is a
magic number for people’s comprehension. Psychological research has
found that people generally cannot keep track of more than about seven
chunks of information at once (Miller 1956). This discovery has been
applied to an enormous number of disciplines, and it seems safe to
conjecture that most people can’t keep track of more than about seven
routine parameters at once.
In practice, how much you can limit the
number of parameters depends on how your language handles complex data
types. If you program in a modern language that supports structured
data, you can pass a composite data type containing 13 fields and
think of it as one mental “chunk” of data. If you program in a more
primitive language, you might need to pass all 13 fields individually,
If you find yourself consistently passing more than a few arguments,
the coupling among your routines is too tight. Design the routine or
group of routines to reduce the coupling. 1f you are passing the same
data to many different routines, group the routines into a class and
treat the frequently used data as class data.
Quoted text from the original post's image
The reason for this is to avoid breaking changes. For example, your class may wish to include further information with it's event, however every thing which used that event would break, as the delegate no longer matched. By having a strict delegate, your event can encapsulate more information in the future without affecting any subscribers.
Edit: As per the comments I'll expand on how this affects the reduction of breaking changes.
If we wished to add further information to our raised event, by using a single class derived from EventArgs new properties/methods can be added. This will mean any existing subscribers to the event will require no change, as the addition of these properties does not affect them. The only required change would be where these properties are set/used, e.g. where the event is raised.
The benefit is the pattern; and having a pattern gives both consistency and the the ability to use other APIs across multiple event types:
The EventHandler<T> delegate type (you don't need to define your own delegate type).
The Reactive Extensions (Rx) have conversion of an event into an IObservable<T> allowing use of LINQ on event sources with Observable.FromEvent.
Also you've got the signatures wrong:
The delegate takes two arguments: object source and SomethingEventArgs
The SomethingEventArgs type inherits EventArgs.
Thus your code should be, to be an exemplar of the pattern:
At namespace scope:
public class SomethingEventArgs : EventArgs {
public string Name;
public int Index;
public double Groar;
}
public delegate void SomethingSomething(object source, SomethingEventArgs e);
and in the type exposing the type
public event SomethingSomething OnSomethingSomething;
(An event could also be internal.)
As others have pointed out, there are maintainability and concistency reasons for this. The EventArgs approach also makes it possible for the event handler to modify the EventArgs.
One reason for modifying the EventArgs is errorhandling. An exception caught somewhere on a background thread is communicated to the client as an event. The client can set a flag in the EventArgs to indicate the exception was handled an shouldn't be rethrown on the background thread.
Another example is the ObjectDataSource class that lets the client supply an object instance when one is required. This is done by subscribing to the ObjectDataSource.ObjectCreating event and supplying the object instance by setting a member of the EventArgs.
Using a class allows the event's subscribers to effect the outcome.
When you pass an instance of a class as a parameter to a method, it is passed by reference. This allows the object instance to change during the method call. Those changed values can then be read by the caller after the event is raised.
For instance:
Look at the FormClosingEventHandler Delegate (in Windows Forms).
This delegate uses a parameter of type FormClosingEventArgs.
If a subscriber to an event using this delegate sets the Cancel property (inherited by CancelEventArgs) to true, then the form is not closed.
In addition, these answers are also correct:
jgauffin
Baszz
Firstly, the reason why this pattern is so common (as you have asked) is because Microsoft has specifically prescribed so when they developed the Event Pattern (yes they coined this term, too). I don't necessarily think this is better or worse than coming up with your own delegate signatures, but following a well-known convention can have its advantages.
Per Microsoft:
The return type is Void.
The first parameter is named sender and is of type Object. This is the object that raised the event.
The second parameter is named e and is of type EventArgs or a derived class of EventArgs. This is the event-specific data.
The method takes exactly two parameters.
To get more at the point of your question, though, I think the rationale for using EventArgs is twofold:
So that classes that inherit from your class can still raise the event, with a derived EventArgs class.
So that classes that handle your event can use common event handlers to handle several types of events, even if different events use different EventArgs. Or, if you change the event down the road, any classes that already handle the event don't need to change their code because the handlers will still be compatible with the new event.
For further reading, see more info from Microsoft:
More info about how to design events: http://msdn.microsoft.com/en-us/library/ms229011.aspx
A detailed how-to on using this pattern: http://msdn.microsoft.com/en-us/library/w369ty8x.aspx
In order to follow the .net standards, the recommanded way to create an event is:
Create a class that inherits from EventArgs
Use the EventHandler<T> generic delegate
As doing so reduces the amount of work required to subsequently change the number and types of values sent to event subscribers.
Example:
public event EventHandler<SometingEventArgs> SomethingEvent;
class SomethingEventArgs
{
public string Name;
public int Index;
public double Groar;
}
In addition to the backward-compatibility convention that others have already mentioned, the EventArgs class enables more control over how the parameters are contiguously accessed as they are passed to more than one object.
This control can be used to make certain values immutable, so that if an event is sent to 3 different subscribers you can guarantee it's not tampered with.
At the same time you can offer multiple [out] values, and you don't have to juggle return values or [ref] parameters, which significantly complicates the multicasting process. It also ensures that any validation logic occurs in the EventArgs subclass, NOT in the class that fires the events.

Should a delegate be declared inside the class that will raise the event, or outside?

I have seen various examples of event handling. Here is one: Event Sample.
Sometimes I see the delegate declared outside the class that will raise the event (as in the link above), and sometimes inside (where I think it should be declared).
It makes more sense to me to declare the event inside the class that will raise the event. The reason being that the event that the class will declare is really just some sugar coating for helper methods etc. that are really doing the adding to, subtracting from, and invoking of the delegate etc.
Are there any best practices? Are there times when you would want to declare the delegate outside, and other times where you would want to declare the delegate inside? If so, how should it be decided which to do?
Typically, these days you'd create your own class derived from EventArgs, and then just use EventHandler<TEventArgs> - there's no need to create a separate delegate type. So instead of AlarmEventHandler, you'd use EventHandler<AlarmEventArgs>. The EventArgs-derived class should generally be top-level (i.e. non-nested).
I would declare them outside as they are ment to be used by other classes as well - the consumers of the event. I would keep the delegate in the same file as the class if the delegate is specific to this class.
It's less of the problem if you use generic version of EventHandler<TEventAgrs>, available in .NET 2.0 and newer, as you need to declare your custom EventArgs only.
If I remember correctly, there are few examples of public accessible nested "objects" in the CLR (classes/structs/delegates/enums). So delegates normally are "external" to the class.
BUT from the .NET 3.5 onward there has been the idea of using "generic" delegates (Func<T>, Action<T>, Predicate<T>) instead of an ever-increasing number of incompatible delegates

Categories

Resources