Loading...

Delegates and Events in C#

Learn delegates and events in C# to build event-driven applications using callbacks, subscriptions, and real-world examples.

In C#, delegates and events are the foundation of event-driven programming. A delegate is a type-safe reference that can point to a method. An event allows a class to notify the outside world that “a certain action has occurred.” These mechanisms enable loosely coupled architectures and make it possible to dynamically execute different methods.


What is a Delegate?

A delegate holds references to methods with a specific signature (parameters and return type). In other words, they are “structures that can carry methods like variables.” A single delegate variable can point to different methods and invoke them when needed.


// A delegate definition
public delegate void Notify(string message);

class Program
{
    static void SendEmail(string message)
    {
        Console.WriteLine("Email sent: " + message);
    }

    static void SendSms(string message)
    {
        Console.WriteLine("SMS sent: " + message);
    }

    static void Main()
    {
        Notify notifyHandler;

        // Assign a method to the delegate
        notifyHandler = SendEmail;
        notifyHandler("Meeting is at 10:00 AM.");

        // Attach another method to the same delegate (multicast)
        notifyHandler += SendSms;
        notifyHandler("New product is live!");
    }
}

In this example, the notifyHandler delegate calls both the SendEmail and SendSms methods. Delegates make it possible to dynamically route events to different methods.


What is an Event?

An event is a mechanism that signals when an action has occurred. It is usually delegate-based. The event keyword is used for declaration, and it can only be accessed externally with += (subscribe) or -= (unsubscribe). This ensures that the event can only be triggered inside the class and not controlled from the outside.


public class Button
{
    // Event definition (EventHandler is a standard delegate type)
    public event EventHandler? Click;

    public void SimulateClick()
    {
        Console.WriteLine("Button clicked!");
        // Trigger the event
        Click?.Invoke(this, EventArgs.Empty);
    }
}

class Program
{
    static void Main()
    {
        var btn = new Button();

        // Subscribe to the event
        btn.Click += (s, e) => Console.WriteLine("Event: Button was clicked.");

        btn.SimulateClick();
    }
}

Here, the Button class publishes a Click event. The subscribed code (lambda expression) executes when the event is triggered. This approach is commonly used in UI applications such as WinForms and WPF.


EventHandler and EventArgs

In C#, the most commonly used standard delegate for events is EventHandler. With EventArgs or classes derived from it, additional information about the event can be passed along.


public class OrderEventArgs : EventArgs
{
    public int OrderId { get; }
    public decimal Amount { get; }

    public OrderEventArgs(int orderId, decimal amount)
    {
        OrderId = orderId;
        Amount = amount;
    }
}

public class OrderService
{
    public event EventHandler<OrderEventArgs>? OrderCreated;

    public void CreateOrder(int id, decimal amount)
    {
        Console.WriteLine($"Order created (ID={id}, Amount={amount})");

        // Trigger the event
        OrderCreated?.Invoke(this, new OrderEventArgs(id, amount));
    }
}

class Program
{
    static void Main()
    {
        var service = new OrderService();

        service.OrderCreated += (s, e) =>
        {
            Console.WriteLine($"Notification: Order received (#{e.OrderId}, {e.Amount} USD)");
        };

        service.CreateOrder(101, 250m);
    }
}

In this example, the OrderService class triggers the OrderCreated event whenever a new order is created. The subscribed code receives the order information via EventArgs.


When to Use Delegates and Events?


TL;DR

  • delegate: Type-safe references that point to methods.
  • event: A mechanism that notifies subscribers when an action occurs.
  • EventHandler and EventArgs: Provide standard usage in events.
  • Delegates → for invocation and routing, Events → for notification and subscription.

Related Articles