Event and delegate: what is the difference?

In order to better understand, I wanted to know the difference between event and delegate and also the use of the += and -= operators for methods in C#

Author: Vadim Ovchinnikov, 2013-06-06

2 answers

Let's start by saying that event and delegate are two different things, as different as a car and a carrot. The difference between a delegate field and an event is about the same as between a field and a property: event sometimes looks like a delegate field. Let's get this straight.

delegate - this is the class, which contains the" template " of the method, that is, the signature of the method. Delegate type variable - type object MulticastDelegate (more precisely, derived from it), which can contain one or more objects representing methods with a "pattern" - compatible signature (counter-and covariance complicates the picture a little). That is, it is like a variable that can contain functions . For such variables, the operation + is defined, which combines the summands of the function into one new function, and the symmetric operation -. These operations automatically generate derived operations += and -=.

event the same is simply a pair of methods in a class, denoted as add and remove, and having arbitrary semantics chosen by the programmer. (Analog-getter and setter properties.) In the implementation, by default, a hidden delegate type field is created for the event, and add/remove methods are added or removed from it (under lock). (To confuse the picture a bit, this hidden field is accessible by the same name as event.)add/remove, components event, are called as += and -=, respectively. No operations +/-, of course not.


Let's go over the difference between an event in a class and a public field of the delegate type.

Consider the case where event is implemented "by default", that is, with an implicit delegate field. The difference is that:

1) For a delegate field, you have full access to it. You can - also outside the classroom! - parse MulticastDelegate to you can replace it with your own or assign it to null, you can call it, you can copy it to yourself in a variable. You have full access, just like any public field. (This, of course, blatantly violates encapsulation.)

For an event, you can only write instance.Event += handler and instance.Event -= handler, which is displayed on the functions add and remove, which in turn again call += and -= for an automatically implemented delegate. No other access you don't have one. Inside the class, however, you can read the value of this delegate using the event name. (This is necessary, for example, in order to call this delegate; VB, unlike C#, has a special method RaiseEvent with the necessary checks.)

2) Another subtle difference (already mentioned in the comments to other answers) is that add/remove they are called under lock, which makes them thread-safe. However, the thread safety of events is very complex (almost impossible). said "impossible in principle") (see article [2]), so this difference is not significant with proper programming: operations with an event usually should occur in only one thread. Note that lock is not available outside add/remove, so you won't be able to copy the delegate to a local variable below it for a thread-safe call*:

void Raise()
{
    EventHandler copy;
    lock (<sorry, not available>)
        copy = MyEvent;
    if (copy != null)
        copy(...);
}

For the case when event is implemented not "by default", there is practically nothing in common. The add and remove methods can do anything:

int subscriberCount = 0;
public event EventHandler MyEvent
{
    add { subscriberCount++; }
    remove { subscriberCount--; }
}

Programmer can start a delegate on its own and "put" signed handlers there, but this is basically its good will. On the other hand, it is still recommended not to break the class semantics expected by clients, and to use event as intended.

References:

  1. Jon Skeet: Delegates and Events
  2. Eric Lippert: Events and races

In addition, the keyword delegate is used to declare an anonymous function (the older parallel syntax for lambda expressions ).


*In modern versions of C#, the MyEvent?.Invoke(...) pattern is recommended for thread-safe calls. However, with thread safety, events are not all smooth, as explained in the article [2].

 55
Author: VladD, 2017-08-16 15:39:07

The main difference between event and delegate is that event can only be started in the class in which it is declared. In addition, if there is an event, the compiler creates not only the corresponding private delegate field, but also two public methods for subscribing and canceling events.

Among the smaller differences, it is worth remembering that an event, unlike a delegate, can be a member of an interface. This is because delegates are always fields, whereas interfaces do not contain fields. can. In addition, an event, unlike a delegate, cannot be a local variable in a method.

And in general, about events and their relationship with delegates, read Richter, chapter 11, which is called "Events"

 28
Author: DreamChild, 2013-06-06 10:05:24