CodeGym /Courses /C# SELF /Publisher-Subscriber pattern and events in C# ( event)

Publisher-Subscriber pattern and events in C# ( event)

C# SELF
Level 52, Lesson 0
Available

1. Introduction

Working with programs, you inevitably run into situations where one part needs to "notify" others that something important happened. A classic example — the user clicked the mouse, and that event needs handling. In everyday life we already live in a world of events: the kettle on the stove starts whistling — you hear the signal and hurry to turn off the heat. Coffee spilled on the keyboard — your heart skipped — and you rush to save the laptop. Programming follows the same rules.

Event is a mechanism that allows a source object (publisher) to notify other objects (subscribers) about changes or actions that occurred. It's a kind of "I broadcast — whoever listened, responded".

In C# events are a special construct based on a delegate type. A delegate defines the callback signature — what and how will be called on subscribers. An event is declared with the keyword event, and a delegate with the keyword delegate.

Why do we need events?

  • Loosely coupled code: The publisher doesn't know about subscribers — it only emits a signal.
  • Flexible architecture: You can dynamically add and remove handlers without changing publisher code.
  • Scalability: Add a new subscriber — and it immediately starts receiving notifications.

Classic Publisher-Subscriber pattern

Imagine we have a class "FireAlarm" (publisher) and a class "PersonInBuilding" (subscriber). When the alarm goes off, it signals everyone at once — no matter how many people are in the building or where exactly. That's the Publisher-Subscriber (or Observer) pattern.

The publisher doesn't know how many or which subscribers exist — it just notifies, and others subscribe to or ignore notifications themselves.

How does this work in C#?

  • Publisher: defines an event (event), provides subscribe/unsubscribe.
  • Subscriber: subscribes to the event and implements a handler (the handler method will be called when the event occurs).

2. Events in practice: first example

Moving from the house to code, let's describe the simplest model. Suppose we have a console app where a timer object "ticks" every second, and different handlers react (for example, write "tick" to the console or count ticks).

Step 1. Define the delegate and event


public class SimpleTimer
{
    // Declare a delegate for the event
    public delegate void TickEventHandler(object sender, EventArgs e);

    // Event based on the delegate
    public event TickEventHandler Tick;

    public void Start(int count)
    {
        for (int i = 0; i < count; i++)
        {
            System.Threading.Thread.Sleep(1000); // tick simulation!
            OnTick(); // raise the event!
        }
    }

    protected virtual void OnTick()
    {
        // Invoke the event if there are subscribers (Tick != null)
        Tick?.Invoke(this, EventArgs.Empty);
    }
}

What's happening here?

  • Declared delegate TickEventHandler with the classic signature object sender, EventArgs e.
  • Event Tick — the subscription point for handlers.
  • Method Start simulates "ticking" and calls OnTick on timer.
  • In OnTick the event is invoked safely: Tick?.Invoke(..., EventArgs.Empty).

Step 2. Subscribing to the event


class Program
{
    static void Main()
    {
        var timer = new SimpleTimer();

        // Subscribe to the Tick event
        timer.Tick += Timer_Tick;

        timer.Start(3);

        // You can unsubscribe if needed
        timer.Tick -= Timer_Tick;
    }

    static void Timer_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("Tick!");
    }
}

We create the timer, subscribe using the += operator, then the handler is called on each tick. Unsubscribe with the -= operator.

3. Useful nuances

Why are events better than "hard" calls?

If SimpleTimer wrote directly to the console inside OnTick, the class would be tightly coupled to a specific action. Events "free" the code: the timer doesn't know what subscribers will do — launch a rocket, log to a file, or send an e-mail.

Important difference between events and delegates

  • Delegate is a "pointer" to a method, while an event is a delegate with access restrictions.
  • Subscribers can only subscribe/unsubscribe; the event can't be raised from outside — only the publisher can do that.
  • To declare an event, add the event modifier to the delegate type — the compiler provides the correct access model.

Brief diagram of how an event works in C#


+------------------+          +------------------------------+
|                  |          |                              |
|     Publisher    | <------> |         Subscriber           |
| (Publisher/Event)|          |      (Subscriber/Handler)    |
|                  |          |                              |
+------------------+          +------------------------------+
         | 1) declares event        | 2) subscribes to it
         | 3) raises it             | 4) implements handler

When to use events?

  • You need to notify an unknown number of listeners about something.
  • You don't want to tie action logic inside the source class.
  • UI, asynchronous interactions, system notifications — it's all about events.

Short implementation notes about C# events

  • An event can't be invoked "from outside": only publisher code has the right to Invoke.
  • Subscribe/unsubscribe: operators +=/-=; there can be multiple handlers.
  • An event is basically a list of delegates: when the event occurs, all handlers are called in subscription order.
  • Recommended delegates: use EventHandler and EventHandler<TEventArgs> for .NET ecosystem compatibility.

4. Common beginner mistakes

They forget to check for subscribers: Tick != null. It's better to use safe invocation: Tick?.Invoke(...).

They subscribe to an event but don't unsubscribe when the handler is no longer needed. This can keep objects alive in memory and lead to leaks.

They try to "call" the event from an external class — the compiler won't allow it. You can't write something like game.GameOver() if that's an event and not a method.

They don't follow the delegate signature. For events use the standard EventHandler or EventHandler<TEventArgs> — this keeps your code compatible with other .NET libraries.

2
Task
C# SELF, level 52, lesson 0
Locked
Creating an Event and a Subscriber
Creating an Event and a Subscriber
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION