C#  

Introduction to Delegates in C#

Introduction

In C#, a delegate is a type that holds a reference to a method. Instead of calling a method directly, a delegate allows the method to be stored in a variable and executed later. This makes the application more flexible and dynamic because the exact method to be executed can be determined at runtime.

Delegates are commonly used when one part of a program needs to inform another that an event has occurred, without tightly coupling the two parts. This concept is widely used in events, callbacks, LINQ, middleware pipelines, and asynchronous programming.

unnamed (2)

Real-Life Analogy of Delegates

Imagine a remote control and a television.

The remote control does not know how the TV works internally. It only knows that when a button is pressed, some action should happen. The same remote can work with different TVs as long as they follow the same command rules.

In this analogy:

  • The remote control is the delegate

  • The button action is the delegate invocation

  • The TV functions (volume up, power on) are the methods

The remote does not care which exact TV method is executed. This is exactly how delegates work in C#.

Why Delegates Are Needed in C#

Without delegates, method calls are tightly coupled. The calling code must know exactly which method to call. This becomes difficult to manage in large applications where behavior needs to change dynamically.

Delegates solve this by allowing methods to be passed as parameters, stored in variables, and invoked when required. This improves code reusability, separation of concerns, and flexibility.

Declaring and Using a Delegate

Step 1: Declare a Delegate

public delegate void Notification(string message);

This delegate can point to any method that:

  • Returns void

  • Accepts a single string parameter

Step 2: Create Methods Matching the Delegate Signature

public class AlertService
{
    public static void EmailAlert(string message)
    {
        Console.WriteLine("Email sent: " + message);
    }

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

Step 3: Assign and Invoke the Delegate

class Program
{
    static void Main()
    {
        Notification notify;

        notify = AlertService.EmailAlert;
        notify("Server down");

        notify = AlertService.SmsAlert;
        notify("Low balance");
    }
}

Explanation

Here, the delegate decides which alert method should run. The calling code does not change — only the assigned method changes.

Single-Cast Delegate Explained

A single-cast delegate refers to only one method at a time. When invoked, only that method is executed.

This is useful when one action should result in exactly one response, such as a callback after a task completes.

Real-Life Example

Submitting an online form where only one confirmation action is required, such as sending an email.

Multicast Delegate Explained

A multicast delegate can hold references to multiple methods. When the delegate is invoked, all methods are executed one by one.

Real-Life Example

When an order is placed:

  • Send email

  • Log order

  • Notify admin

All these actions happen from one trigger.

Program Example

public delegate void OrderProcess(string orderId);

public class OrderService
{
    public static void SendEmail(string orderId)
    {
        Console.WriteLine("Email sent for order: " + orderId);
    }

    public static void LogOrder(string orderId)
    {
        Console.WriteLine("Order logged: " + orderId);
    }

    public static void NotifyAdmin(string orderId)
    {
        Console.WriteLine("Admin notified for order: " + orderId);
    }
}

class Program
{
    static void Main()
    {
        OrderProcess processOrder;

        processOrder = OrderService.SendEmail;
        processOrder += OrderService.LogOrder;
        processOrder += OrderService.NotifyAdmin;

        processOrder("ORD123");
    }
}

Explanation

All three methods are executed when processOrder is invoked. This demonstrates how one action can trigger multiple behaviors.

Delegates as Method Parameters (Very Important Concept)

Delegates allow you to pass behavior as a parameter.

Real-Life Example

A payment system where the payment logic can change (Credit Card, UPI, Net Banking).

Program Example

public delegate void PaymentMode(double amount);

public class PaymentService
{
    public static void CreditCard(double amount)
    {
        Console.WriteLine("Paid using Credit Card: " + amount);
    }

    public static void UPI(double amount)
    {
        Console.WriteLine("Paid using UPI: " + amount);
    }
}

public class Checkout
{
    public static void ProcessPayment(PaymentMode payment, double amount)
    {
        payment(amount);
    }
}

class Program
{
    static void Main()
    {
        Checkout.ProcessPayment(PaymentService.CreditCard, 2500);
        Checkout.ProcessPayment(PaymentService.UPI, 1800);
    }
}

Explanation

The checkout process remains the same. Only the payment logic changes dynamically using delegates.

Built-in Delegates (Func, Action, Predicate)

C# provides built-in delegates to avoid creating custom delegates repeatedly.

Action Example

Action<string> printMessage = msg => Console.WriteLine(msg);
printMessage("Hello from Action delegate");

Func Example

Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(10, 20));

Predicate Example

Predicate<int> isEven = number => number % 2 == 0;
Console.WriteLine(isEven(4));

These are heavily used in LINQ and modern C# applications.

Delegates and Events

Events are built on delegates. Delegates define what kind of method can respond, and events control who can subscribe or unsubscribe.

In UI applications, when a button is clicked, an event is raised, and subscribed delegate methods are executed.

This allows loose coupling between the event source and the event handler.

Advantages of Delegates

Delegates improve flexibility, support loose coupling, enable runtime behavior changes, and make code more reusable. They also improve readability when used correctly and are type-safe, reducing runtime errors.

Delegates vs Interfaces

Delegates represent a single behavior or action, while interfaces represent a complete contract with multiple methods. Delegates are lightweight and ideal for callbacks and events, whereas interfaces are better for long-term dependencies.

Delegates are a core feature of C# that allow methods to be treated as data. They enable dynamic behavior, event-driven programming, and flexible application design. From simple callbacks to enterprise-level frameworks, delegates play a vital role in modern C# development.

Mastering delegates strengthens your understanding of events, LINQ, middleware, and clean architecture patterns.