C# Delegates

Delegates are type-safe function pointers in C#. They provide a mechanism for invoking methods indirectly and are fundamental to implementing event handlers and callback patterns.

What is a Delegate?

A delegate is a reference type that represents references to methods with a particular parameter list and return type. When you create a delegate instance, you can associate it with any method that has a matching signature (same return type and same parameter types).

Delegate Declaration

You declare a delegate using the delegate keyword. The syntax is similar to a method signature, but without a method body.


public delegate void MyDelegate(string message);

This declares a delegate named MyDelegate that can point to methods returning void and accepting a single string argument.

Using Delegates

To use a delegate, you typically perform these steps:

  1. Declare the delegate.
  2. Define one or more methods that match the delegate's signature.
  3. Create an instance of the delegate, associating it with a method.
  4. Invoke the delegate to call the associated method(s).

1. Declaring a Delegate


// Declare a delegate that can point to methods
// that take an int and return an int.
public delegate int MyMathOperation(int x, int y);

2. Defining Methods


public class Calculator
{
    public static int Add(int a, int b)
    {
        return a + b;
    }

    public static int Subtract(int a, int b)
    {
        return a - b;
    }
}

3. Instantiating and Invoking a Delegate


// Create a delegate instance pointing to the Add method.
MyMathOperation operation = new MyMathOperation(Calculator.Add);

// Invoke the delegate.
int result = operation(5, 3); // result will be 8

// You can also reassign the delegate to point to another method.
operation = Calculator.Subtract;
result = operation(10, 4); // result will be 6

Multicast Delegates

Delegates can also point to multiple methods. This is known as a multicast delegate. When you invoke a multicast delegate, all the methods it points to are executed sequentially.

Multicast Delegate Example

You can use the + and - operators to add or remove methods from a delegate instance.


public delegate void MyNotification(string notification);

public class UserManager
{
    public void SendEmail(string message)
    {
        Console.WriteLine($"Sending email: {message}");
    }

    public void SendSMS(string message)
    {
        Console.WriteLine($"Sending SMS: {message}");
    }
}

// In another part of your code:
UserManager userManager = new UserManager();

MyNotification notificationDelegate = userManager.SendEmail; // Start with one method

// Add another method to the delegate
notificationDelegate += userManager.SendSMS;

// Invoke the delegate - both methods will be called
notificationDelegate("User logged in!");

// Remove a method
notificationDelegate -= userManager.SendEmail;

// Invoke again - only SendSMS will be called
notificationDelegate("User profile updated.");

Output:


Sending email: User logged in!
Sending SMS: User logged in!
Sending SMS: User profile updated.

Event Handlers and Delegates

Delegates are the backbone of C#'s event handling mechanism. Events are essentially a way to declare a delegate type and then declare a field of that delegate type. This allows objects to broadcast messages (events) to other objects that have registered to listen.

Common Delegate Types

The .NET Framework provides several built-in generic delegate types that cover most common scenarios:

Using Built-in Delegates (Func)


// Using Func for a method that returns a value
Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(7, 6); // product will be 42

// Using Action for a method that returns void
Action<string> printMessage = Console.WriteLine;
printMessage("Hello from Action delegate!");

Key Benefits of Delegates