C#  

Delegates in C# – Explanation & Use Cases

1. Introduction

In C#, a delegate is a type that holds a reference to a method. Delegates are similar to function pointers found in other programming languages, but they are type-safe and secure. They form an essential part of the C# language, enabling programmers to write flexible, scalable, and maintainable applications. Delegates allow methods to be passed as parameters, stored as variables, and invoked dynamically at runtime.

2. Definition of a Delegate

A delegate is defined using the delegate keyword followed by the method signature it can represent. Once declared, it can store a reference to any method that matches its signature.

Example of declaring a delegate:

public delegate void MyDelegate(string message);

This delegate can point to any method that accepts a string parameter and returns void.

3. Purpose of Delegates

Delegates provide several important advantages in C# programming:

  1. They allow methods to be passed as arguments.

  2. They support callback mechanisms.

  3. They promote loose coupling between components.

  4. They enable dynamic method invocation.

  5. They serve as the foundation for events, lambda expressions, and LINQ.

4. Declaring and Using Delegates

4.1 Creating a Method

public static void DisplayMessage(string message)
{
    Console.WriteLine("Message: " + message);
}

4.2 Assigning the Method to a Delegate

MyDelegate del = DisplayMessage;
del("Hello from delegate.");

When invoked, the delegate calls the method it refers to.

5. Types of Delegates

5.1 Single-Cast Delegates

A single-cast delegate refers to one method at a time.

MyDelegate del = DisplayMessage;

5.2 Multi-Cast Delegates

A multi-cast delegate can refer to multiple methods. Methods are combined using the += operator.

del += AnotherMethod;
del("Test");

When invoked, all assigned methods run in sequence.

6. Anonymous Methods

C# allows the declaration of anonymous methods using the delegate keyword. These are useful when a method is required only once or when defining callback functions.

MyDelegate del = delegate(string msg)
{
    Console.WriteLine(msg);
};
del("Anonymous method executed.");

7. Delegates and Lambda Expressions

With the introduction of lambda expressions in C# 3.0, writing delegate-based logic became simpler and more concise.

MyDelegate del = msg => Console.WriteLine(msg);
del("Lambda expression executed.");

Lambda expressions help make code more readable and reduce unnecessary boilerplate.

8. Built-in Delegates in C#

8.1 Action Delegate

Represents a method that returns void.

Action<int> print = x => Console.WriteLine(x);
print(10);

8.2 Func Delegate

Represents a method that returns a value.

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

8.3 Predicate Delegate

Represents a method that returns a boolean value.

Predicate<int> isEven = x => x % 2 == 0;
Console.WriteLine(isEven(10));

9. Practical Use Cases of Delegates

9.1 Callback Mechanisms

Delegates are commonly used to implement callback functions, where one method notifies another when a task has been completed.

public delegate void Callback();

public static void Process(Callback callback)
{
    Console.WriteLine("Processing...");
    callback();
}
Process(() => Console.WriteLine("Completed."));

9.2 Custom Sorting Logic

Delegates allow developers to define custom sorting logic for collections.

List<int> numbers = new List<int>() { 5, 2, 8, 1 };
numbers.Sort((a, b) => a.CompareTo(b));

9.3 Event Handling

C# events are based on delegates. When an event is triggered, all associated delegate methods are executed.

public delegate void Notify();

public class Process
{
    public event Notify Completed;

    public void Start()
    {
        Console.WriteLine("Working...");
        Completed?.Invoke();
    }
}

9.4 Plugin and Strategy Design Pattern

Delegates enable dynamic selection of methods at runtime. This is beneficial in applications where behavior needs to be interchangeable without modifying core logic.

9.5 LINQ Operations

LINQ relies heavily on delegates and lambda expressions to perform filtering, mapping, and querying operations.

var evenNumbers = numbers.Where(n => n % 2 == 0);

10. Advantages of Delegates

Delegates offer numerous benefits:

  1. Improved flexibility and reusability of code

  2. Enhanced support for event-driven programming

  3. Promotion of loose coupling between components

  4. Foundation for modern C# features such as LINQ, events, async callbacks, and lambda expressions

11. Conclusion

Delegates are a fundamental feature of the C# programming language. They allow methods to be treated as first-class entities, enabling dynamic invocation and flexible programming structures. Delegates support callback functions, event handling, custom sorting, functional programming, and several advanced features. Understanding delegates is essential for writing clean, modular, and efficient C# applications.