Delegates vs Events

Trying to glean some notes from https://docs.microsoft.com/en-us/dotnet/csharp/distinguish-delegates-events. All text is from that page (emphasis is mine).

The most important consideration in determining which language feature to use is whether or not there must be an attached subscriber. If your code must call the code supplied by the subscriber, you should use a design based on delegates when you need to implement callback. If your code can complete all its work without calling any subscribers, you should use a design based on events.

Another consideration is the method prototype you would want for your delegate method. As you’ve seen, the delegates used for events all have a void return type. You’ve also seen that there are idioms to create event handlers that do pass information back to event sources through modifying properties of the event argument object. While these idioms do work, they are not as natural as returning a value from a method.

That event listeners have longer lifetimes is a slightly weaker justification. However, you may find that event-based designs are more natural when the event source will be raising events over a long period of time. You can see examples of event-based design for UX controls on many systems. Once you subscribe to an event, the event source may raise events throughout the lifetime of the program. (You can unsubscribe from events when you no longer need them.)

Contrast that with many delegate-based designs, where a delegate is used as an argument to a method, and the delegate is not used after that method returns.


Also found some good notes here: https://www.tutorialsteacher.com/articles/difference-between-delegate-and-event-csharp:

An event is dependent on a delegate and cannot be created without delegates. Event is a wrapper around delegate instance to prevent users of the delegate from resetting the delegate and its invocation list and only allows adding or removing targets from the invocation list.

In a way, an event is a delegate only. The program code will work even if you remove the event keyword and only use a delegate. However, using the event keyword, we prevent subscribers to register with an event by using = operator and thereby removing all handlers.


Some notes from Illustrated C# 7:

One pattern for notifying parts of a program that an event has occurred is called publisher/subscriber. A class called the publisher defines a set of events that other parts might be interested in. The publisher raises the event and all methods submitted by subscribers are called. Methods supplied by subscribers are called callback methods or event handlers.

Many aspects of events are similar to those of delegates. An event contains a private delegate. It’s a common error to think of an event as a type. Like a method, or a property, an event is a member of a class or struct. An event member is implicitly initialized to null with the other members.

Declaring an event: public event DelegateType NameOfEvent;

Events can also be declared static: public static event DelegateType NameOfEvent;

Subscribing to an event: instance.NameOfEvent += MyHandler;

Example of raising an event:

using System;

namespace SimpleTests
{
    delegate void Handler();

    // Incrementer is a Publisher
    class Incrementer
    {
        public event Handler CountedADozen;

        public void DoCount()
        {
            for (int i = 1; i < 100; i++)
            {
                if (i % 12 == 0 && CountedADozen != null)
                    CountedADozen();
            }
        }
    }

    // Dozens is a Subscriber (there could be others)
    class Dozens
    {
        public int DozensCount { get; private set; }

        public Dozens(Incrementer inc)
        {
            DozensCount = 0;
            inc.CountedADozen += IncrementDozensCount;
        }

        void IncrementDozensCount()
        {
            DozensCount++;
        }
    }

    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozensCounter = new Dozens(incrementer);

            incrementer.DoCount();

            Console.WriteLine("Number of dozens = {0}", dozensCounter.DozensCount);
        }
    }
}

GUI programming is event driven. I can be interrupted at any time by button presses, key presses, or system timers.

Standard event usage: public delegate void EventHandler(object sender, EventArgs e);

Extending EventArgs: public class IncrementerEventArgs : EventArgs { public int Count { get; set; } }

Using generics: public event EventHandler<IncrementerEventArgs> CountedADozen;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s