C#  

What are delegates and multicast delegates in C#

A delegate in C# is a type-safe function pointer that can reference methods with a particular signature. It allows methods to be passed as parameters, assigned to variables, and invoked dynamically. Delegates are a fundamental part of building flexible, extensible, and event-driven applications in C#.

Think of a delegate as a contract: any method that matches the signature can be used with the delegate.

πŸ”§ Delegate Syntax

Declare and use a delegate:

// 1. Declare a delegate
public delegate void GreetDelegate(string name);

// 2. Create methods that match the delegate signature
public class Greeter
{
    public void EnglishGreeting(string name)
    {
        Console.WriteLine($"Hello, {name}!");
    }

    public void SpanishGreeting(string name)
    {
        Console.WriteLine($"Β‘Hola, {name}!");
    }
}

// 3. Use the delegate
class Program
{
    static void Main()
    {
        Greeter greeter = new Greeter();

        GreetDelegate greet = greeter.EnglishGreeting;
        greet("Alice"); // Output: Hello, Alice!
        
        greet = greeter.SpanishGreeting;
        greet("Alice"); // Output: Β‘Hola, Alice!
    }
}

πŸ” Why Use Delegates?

Delegates help in:

  • Decoupling components (e.g., event publishers and subscribers).
  • Passing behavior as parameters (e.g., callback functions).
  • Implementing events in custom controls or APIs.
  • Encouraging reusable code by separating logic from behavior.

🧰 Built-in Delegate Types

C# provides predefined delegates in the System namespace for convenience:

  • Action - for methods that return void.
  • Func<TResult> - for methods that return a value.
  • Predicate<T> - for methods that return a bool.
Action<string> print = Console.WriteLine;
print("Using Action delegate!");

Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine(add(5, 3)); // Output: 8

🌐 What are Multicast Delegates?

A multicast delegate is a delegate that can hold references to more than one method. When invoked, all methods in the invocation list are called in order.

All delegates derived from System.MulticastDelegate support this feature.

πŸ”— Example of Multicast Delegates

public delegate void Notify(); // No parameters and void return type

class Notifications
{
    public void EmailNotification()
    {
        Console.WriteLine("Email sent.");
    }

    public void SMSNotification()
    {
        Console.WriteLine("SMS sent.");
    }

    public void PushNotification()
    {
        Console.WriteLine("Push notification sent.");
    }
}

class Program
{
    static void Main()
    {
        Notifications notify = new Notifications();

        Notify notifyAll = notify.EmailNotification;
        notifyAll += notify.SMSNotification;
        notifyAll += notify.PushNotification;

        notifyAll(); 
        /*
            Output:
            Email sent.
            SMS sent.
            Push notification sent.
        */
    }
}

βž– Removing Methods from Multicast Delegates

You can remove methods from the invocation list using the -= operator:

notifyAll -= notify.SMSNotification;
notifyAll();
/*
    Output:
    Email sent.
    Push notification sent.
*/

⚠️ Key Notes and Limitations

  • Only the last method's return value is returned if the delegate has a return type.
  • All methods are called in the order they were added.
  • Exceptions in one method can prevent subsequent methods from running unless handled.
public delegate int Calculation();

public static int A() { Console.WriteLine("A"); return 1; }
public static int B() { Console.WriteLine("B"); return 2; }

public static void Main()
{
    Calculation calc = A;
    calc += B;

    int result = calc(); // Output: A B, Result: 2 (from B)
    Console.WriteLine("Result: " + result);
}

🎯 When to Use Delegates vs Interfaces vs Events?

Use Case Best Choice
Single method behavior injection Delegate
Polymorphism and multiple methods Interface
Notification to subscribers Event/Delegate

πŸ›  Real-World Use Cases

  • Event Handling: Button clicks, UI interactions.
  • LINQ methods: Accept delegates like Func<T, bool>.
  • Callbacks: For asynchronous or background operations.
  • Strategy Pattern: Swap logic at runtime.

πŸ§ͺ Summary

  • βœ… Delegate: A reference to a method with a specific signature.
  • βœ… Multicast Delegate: Chains multiple methods together.
  • βœ… Enables loose coupling, dynamic behavior, and event-driven programming.
  • βœ… Used extensively in .NET event systems and LINQ.

πŸ“ Final Thoughts

Understanding and mastering delegates is essential for writing clean, maintainable, and extensible C# applications. Whether you're handling events, implementing design patterns, or building libraries, delegates provide the flexibility and type safety you need.