Start Coding

Topics

C# Delegates: Flexible Function Pointers

Delegates in C# are powerful constructs that act as type-safe function pointers. They provide a way to pass methods as parameters, enabling flexible and reusable code designs.

What are Delegates?

A delegate is a type that represents references to methods with a particular parameter list and return type. They allow methods to be passed as parameters, stored as variables, and invoked dynamically.

Declaring and Using Delegates

To declare a delegate, use the delegate keyword followed by the method signature:


public delegate int MathOperation(int x, int y);
    

Once declared, you can create delegate instances and assign methods to them:


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

MathOperation addDelegate = Add;
MathOperation subtractDelegate = Subtract;

int result1 = addDelegate(5, 3);      // result1 = 8
int result2 = subtractDelegate(10, 4); // result2 = 6
    

Multicast Delegates

C# delegates support multicasting, allowing multiple methods to be invoked through a single delegate instance. This feature is particularly useful for implementing event handling systems.


public delegate void Notifier(string message);

Notifier notifier = Console.WriteLine;
notifier += (msg) => Console.WriteLine($"Log: {msg}");

notifier("Hello, delegates!"); // Invokes both methods
    

Built-in Delegate Types

C# provides several built-in delegate types for common scenarios:

  • Action: For methods that don't return a value
  • Func: For methods that return a value
  • Predicate: For methods that return a boolean

These generic delegates reduce the need for custom delegate declarations:


Action<string> print = Console.WriteLine;
Func<int, int, int> add = (a, b) => a + b;
Predicate<int> isEven = (num) => num % 2 == 0;
    

Delegates and Lambda Expressions

Delegates work seamlessly with lambda expressions, enabling concise inline method definitions:


Func<int, int, int> multiply = (x, y) => x * y;
int product = multiply(4, 5); // product = 20
    

Use Cases for Delegates

  • Callback mechanisms
  • Event handling in C# Events
  • Implementing strategy patterns
  • Customizing sorting and filtering operations

Best Practices

  • Use built-in delegate types when possible
  • Consider using delegates for increased code flexibility
  • Be cautious with multicast delegates, as exceptions in one method can prevent others from executing
  • Utilize delegates in conjunction with events for robust event-driven programming

Delegates are a cornerstone of C#'s functional programming features. They provide a bridge between object-oriented and functional paradigms, enabling more flexible and modular code designs.