52

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?

user
  • 5,335
  • 7
  • 47
  • 63
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348

5 Answers5

47

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.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    So 1. what is that delegate cant do but events can (or vice versa) 2. what is that events should do that delegate should not. This may clear diff more crystal clear. – Dhananjay Apr 30 '12 at 04:23
  • @Dhananjay Events must use delegates in some way, since they are implemented as a pair of methods (add and remove) that take a delegate as a parameter. However they are not required to map directly onto a delegate field. Instead they may store the delegates in some other manner, or they might create a wrapper delegate and store that instead, etc. Users of the class should not be able to tell the difference between an auto-event that uses a delgate backing field, and a custom coded event, so reasonable implementation options are a bit limited. – Kevin Cathcart Apr 30 '12 at 16:09
  • 5
    Tangential: If you could restart C# and .NET from scratch, would you replace events/delegates with something like IObservable? – Judah Gabriel Himango May 01 '12 at 17:51
  • You can do use delegates in place of events but events offer more security such as protecting the delegates from being set null from outside he defining class. I believe this is biggest difference. – Tarik May 04 '12 at 22:45
46

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.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 1
    The classic example to help with understanding this is when using things like winforms - there is an `EventHandlerList` that is the "backer" for most of the events (and which is available, via `.Events`, to subclasses to use). Only 1 field - many many events. – Marc Gravell Apr 28 '12 at 20:18
  • I believe this is done by overriding the `add` and `remove` methods on the event - e.g. the second example of http://msdn.microsoft.com/en-us/library/ak9w5846.aspx – dsolimano Apr 28 '12 at 20:21
  • 4
    @dsolimano "overriding" is probably a confusing term to use here, since that usually relates to polymorphism; **providing a bespoke** `add`/`remove`, sure - a bit like the difference between an automatically implemented property and a regular property (the term for events akin to "automatically implemented property" is "field-like event", btw) – Marc Gravell Apr 28 '12 at 20:34
  • This is a terrific answer +1! – nawfal May 06 '13 at 05:46
26

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.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
10

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • An event is an accessor for a field whose type is a delegate type. – Ben Voigt Apr 28 '12 at 20:36
  • Read the answer to see that's not the case. Last paragraph. – Hans Passant Apr 28 '12 at 20:40
  • 3
    It's just as true as the second sentence in your answer. – Ben Voigt Apr 28 '12 at 21:29
  • Hmm, no, different truths. The point of *not* letting the compiler generate the default implementation with a backing field is that you don't need or want a backing field. Exact same reasoning for properties. This is Skeet's point, *events aren't fields*. – Hans Passant Apr 28 '12 at 22:20
  • 4
    Skeet's point is that events are methods providing access to a value, not the value itself. Just like a property, but with different operations. The value is usually, but not always, stored in a field. Again, just like a property. The level of pedantry involved in saying that an event may not have a backing field also excludes making a general statement that a property is an accessor for a field. – Ben Voigt Apr 28 '12 at 22:25
  • 1
    Ugh, you troll bad. No byte. – Hans Passant Apr 28 '12 at 22:37
0

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.

Shahar G.
  • 1,440
  • 12
  • 22