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

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.