Understanding C# Delegates

Introduction

Delegates in C# are a powerful feature that allows you to encapsulate a reference to a method inside a delegate object. These objects can then be passed around as parameters, stored in collections, or even used as callback methods. Delegates play a significant role in C# programming, especially in scenarios involving events and lambda expressions.

1. What is a Delegate?

In C#, a delegate is a type that safely encapsulates a method with a specific signature and return type. It is similar to function pointers in C and C++, but delegates are object-oriented, type-safe, and secure.

// Define a delegate
public delegate void MyDelegate(string message);

2. How to Use Delegates?

To use a delegate, follow these steps:

  1. Declare the delegate.
  2. Create a method that matches the delegate's signature.
  3. Instantiate the delegate.
  4. Invoke the delegate.

2.1 Declare the delegate

public delegate void DisplayMessage(string message);

2.2 Create a matching method

public class MessageDisplayer
{
    public void ShowMessage(string message)
    {
        Console.WriteLine(message);
    }
}

2.3 Instantiate the delegate

MessageDisplayer displayer = new MessageDisplayer();
DisplayMessage displayDelegate = new DisplayMessage(displayer.ShowMessage);

Or use the shorter syntax:

DisplayMessage displayDelegate = displayer.ShowMessage;

2.4 Invoke the delegate

displayDelegate("Hello, World!");

3. Multicast Delegates

A delegate can reference more than one method. Such delegates are termed as multicast delegates.

public delegate void NumberProcessor(int number);

public class NumberOperations
{
    public void Double(int num)
    {
        Console.WriteLine(num * 2);
    }

    public void Square(int num)
    {
        Console.WriteLine(num * num);
    }
}

NumberOperations operations = new NumberOperations();
NumberProcessor process = operations.Double;
process += operations.Square;

process(5); // Outputs: 10 (from Double) and 25 (from Square)

4. Delegates with Anonymous Methods

You don't always have to create a named method to bind to a delegate. Anonymous methods provide a way to define inline methods.

DisplayMessage display = delegate(string message)
{
    Console.WriteLine(message);
};

display("Anonymous method call!");

5. Lambda Expressions

Lambda expressions offer a more concise way to write anonymous methods.

DisplayMessage displayLambda = message => Console.WriteLine(message);

displayLambda("Lambda call!");

6. Predicate, Action, and Func Delegates

C# provides some built-in generic delegate types to simplify common scenarios:

  • Predicate<T>: Represents a method containing a set of criteria and checks an element against those criteria.
    Predicate<int> isEven = num => num % 2 == 0;
    Console.WriteLine(isEven(4));  // Outputs: True
  • Action<T>: Represents a method that takes a single parameter and does not return a value.
    Action<string> showMessage = message => Console.WriteLine(message);
    showMessage("Action call!");
    
  • Func<T, TResult>: Represents a method that takes a parameter and returns a value.
    Func<int, int> square = num => num * num;
    Console.WriteLine(square(5));  // Outputs: 25
    

Conclusion

Delegates in C# offer a versatile and powerful mechanism for decoupling classes and methods. They serve as the foundation for events, LINQ queries, and more. By understanding and leveraging delegates, you can write more flexible, maintainable, and performant code.


Similar Articles