Codecademy Logo

C# Delegates

C# Multicast Delegates

Delegates in C# can invoke multiple methods in sequence, known as multicast delegation. This feature is beneficial when you need several actions triggered by a single event, improving modular code design.

using System;
// Define a delegate type
public delegate void Notify();
class Program
{
static void Main()
{
// Instantiate the delegate
Notify notifyAll = Alert1;
notifyAll += Alert2; // Multicast: Add another method
// Invokes both Alert1 and Alert2
notifyAll();
}
static void Alert1()
{
Console.WriteLine("Alert 1 called!");
}
static void Alert2()
{
Console.WriteLine("Alert 2 called!");
}
}

C# Delegates

In C#, the Action and Func types are built-in delegates for defining common method signatures in a simplified manner. Action is used for methods without a return value, while Func is for methods with a return value.

// Action delegate example
Action printHello = () => Console.WriteLine("Hello, World!");
printHello();
// Func delegate example
Func<int, int, int> add = (a, b) => a + b;
int result = add(5, 3);
Console.WriteLine(result);

C# delegate Usage

A delegate in C# is a type that references a method. Use delegate to encapsulate a method signature for a specific parameter list and return type. This allows methods to be passed as parameters.

public delegate void MessageDelegate(string message);
public void ShowMessage(string msg) {
Console.WriteLine(msg);
}
// Usage
MessageDelegate del = ShowMessage;
del("Hello, World!");

C# Delegates Basics

Delegates in C# act as type-safe references to methods, enabling encapsulation and callbacks. They delegate the responsibility of executing methods to other code blocks, thus promoting flexibility and reusability in code design.

using System;
public delegate void ShowMessage(string message);
public class Program
{
static void DisplayMessage(string message)
{
Console.WriteLine(message);
}
public static void Main()
{
ShowMessage showMessageDelegate = DisplayMessage;
showMessageDelegate("Hello from the delegate!");
}
}

C# Delegates and Lambda Expressions

C# provides a concise way to create delegate instances using lambda expressions and expression-bodied members. This syntax simplifies the way you write methods and functions by using the => (lambda) operator. This can make your code more readable and maintainable.

using System;
class Program
{
static void Main()
{
Func<int, int> square = x => x * x;
Console.WriteLine(square(5)); // Outputs: 25
}
}

C# Predicate Delegates

Predicate delegates in C# are used for filtering data. They return a boolean value, typically indicating whether an object matches a specific condition. This makes them handy in methods like FindAll() to filter collections efficiently.

List<int> numbers = new List<int>{ 1, 3, 5, 6, 7, 8, 10 };
Predicate<int> isEven = x => x % 2 == 0;
List<int> evenNumbers = numbers.FindAll(isEven);
Console.WriteLine(string.Join(", ", evenNumbers));
// Output: 6, 8, 10

C# delegate Methods

In C#, delegate can be associated with both instance methods and static methods through method group conversion. This allows for flexible referencing and calls to methods dynamically at runtime, enhancing reusability.

using System;
public class Example {
public delegate void PrintDelegate(string message);
// Static method
public static void PrintStatic(string message) {
Console.WriteLine("Static: " + message);
}
// Instance method
public void PrintInstance(string message) {
Console.WriteLine("Instance: " + message);
}
public static void Main() {
Example example = new Example();
// Referencing static method
PrintDelegate printStatic = PrintStatic;
printStatic("Hello from static method");
// Referencing instance method
PrintDelegate printInstance = example.PrintInstance;
printInstance("Hello from instance method");
}
}

C# Scope and Lambda Expressions

C# lambda expressions provide a concise way to create anonymous functions. They can capture variables from their surrounding scope, making them powerful when used with delegates. In the example, notice how the threshold variable, defined in the enclosing scope, is used within the lambda.

using System;
class Program
{
static void Main()
{
int threshold = 10;
Func<int, bool> isAboveThreshold = number => number > threshold;
Console.WriteLine(isAboveThreshold(15)); // Outputs: True
Console.WriteLine(isAboveThreshold(5)); // Outputs: False
}
}

Learn more on Codecademy