A delegate is a type that represents a reference to a function or method. Delegates allow methods to be passed as parameters, assigned to variables, and executed dynamically at runtime.
For this, the delegate must match the signature (parameters received) of the function, and its specific return.
In simple terms, a delegate can be considered as a kind of function pointer, but with the safety and robustness of C#‘s type system.
If you want to learn more about Function References
check out the Introduction to Programming Course read more
Declaring a Delegate
To declare a delegate in C# the keyword delegate
is used, followed by the method signature that the delegate will represent.
delegate ReturnType MyDelegate(ParameterType parameter1...);
Where,
- ReturnType is the return type of the function we want to delegate
- ParameterType…, are the parameters of the function we want to delegate
For example, if we want to declare a delegate that represents a method that does not return any value and takes two integer parameters, the declaration would look like this:
Basic Example
For example, if we wanted to define a delegate that can point to any function that takes a string
as a parameter and does not return any value (void
), we could do it like this:
public delegate void MyDelegate(string message);
And if we want to declare a delegate that references a function that takes two int
parameters and returns a double
, the declaration would look like this:
delegate void MyDelegate(int parameter1, int parameter2);
Using Delegates
Assigning a Method to a Delegate
Once the delegate is declared, we can create an instance of the delegate and assign a method that matches its signature.
For this, we can create it using its constructor
MyDelegate delegate = new MyDelegate(ReferencedFunction);
Or simply assign it
MyDelegate delegate = ReferencedFunction;
Let’s see it with an example. Suppose we have the function ShowMessage(string ...)
.
// Method we want to reference
public static void ShowMessage(string message)
{
Console.WriteLine("Delegate:" + message);
}
// Delegate definition
public delegate void MyDelegate(string message);
public static void Main(string[] args)
{
// Now we create a MyDelegate that points to ShowMessage
MyDelegate delegate = ShowMessage;
}
Here we have,
- Defined a delegate
MyDelegate
, which matches the shape ofShowMessage
. - Created a new instance of
MyDelegate
, calleddelegate
- Assigned the instance
delegate
toShowMessage
.
Invoking a Delegate
Once we have defined the delegate, created a delegate, and referenced a function with it, we can invoke it simply by using ()
as we would with the original function.
In the previous example, we could invoke delegate
like this.
// Invoking the method through the delegate
delegate("Hello, World!");
}
So it would display on the screen
Delegate: Hello, World!
Generic Delegates: Func
and Action
To simplify the use of delegates, C# provides predefined generic delegates.
The most common are Action
and Func
.
Action
: Represents a method that does not return a valueFunc<TResult>
: Represents a method that returns a value of typeTResult
Using Action
Action<string> display = message => Console.WriteLine(message);
display("Hello with Action!");
Using Func
Func<int, int, int> add = (a, b) => a + b;
int result = add(3, 4);
Console.WriteLine("Result of the addition: " + result);
In general, this is the form you will normally use, instead of defining the delegate explicitly. Especially if it is a temporary use, which is not worth defining traditionally.
Multicast Delegates
A Multicast delegate is a delegate that can have more than one method in its invocation. In fact, all C# delegates are Multicast.
We see it in this post read more
Using Delegates with Events
Delegates are the foundation of events in C#. An event is a notification sent by an object to signal the occurrence of an action. Delegates allow subscribing methods that will be called when the event is fired.
We see it in this post read more
Practical Examples
Delegate that Returns Nothing
Here we have an example of a delegate that returns nothing (void
).
// Declaration of the delegate that returns nothing
public delegate void ShowMessageDelegate(string message);
// Method that matches the delegate's signature
public static void ShowMessage(string message)
{
Console.WriteLine(message); // Print the message
}
// Usage
ShowMessageDelegate showMessage = ShowMessage; // Assign the method to the delegate
showMessage("Hello, World!"); // Invoke the delegate
Delegate that Returns a Value
Here is an example of a delegate that returns a value. In the example, the delegate takes two integers as parameters and returns an integer.
// Declaration of the delegate that returns a value
public delegate int SumDelegate(int a, int b);
// Method that matches the delegate's signature
public static int Sum(int a, int b)
{
return a + b; // Return the sum of the two numbers
}
// Usage
SumDelegate sum = Sum; // Assign the method to the delegate
int result = sum(3, 5); // Invoke the delegate and get the result
Console.WriteLine($"Result of the sum: {result}"); // Print the result
Generic Delegate Action
Let’s see an example that uses a generic delegate Action<T>
to represent a method that does not return a value and can take parameters.
// Method that matches the Action signature
public static void PrintMessage(string message)
{
Console.WriteLine(message); // Print the message
}
// Usage
Action<string> print = PrintMessage; // Assign the method to the Action delegate
print("This is a message using Action."); // Invoke the delegate
Generic Delegate Func
Now an example of a generic delegate Func<T>
that can represent a method that returns a value and can take parameters.
// Method that matches the Func signature
public static double CalculateCircleArea(double radius)
{
return Math.PI * radius * radius; // Calculate and return the area of the circle
}
// Usage
Func<double, double> calculateArea = CalculateCircleArea; // Assign the method to the Func delegate
double area = calculateArea(5.0); // Invoke the delegate and get the result
Console.WriteLine($"Circle area: {area}"); // Print the area of the circle
Delegate as a Parameter in a Method
In this example, we will see how to pass a delegate as a parameter to another method,
// Declaration of the delegate that returns nothing
public delegate void OperationDelegate(int x, int y);
// Method that uses a delegate as a parameter
public static void PerformOperation(int a, int b, OperationDelegate operation)
{
operation(a, b); // Invoke the delegate
}
// Methods that match the delegate's signature
public static void Add(int a, int b)
{
Console.WriteLine($"Sum: {a + b}");
}
public static void Multiply(int a, int b)
{
Console.WriteLine($"Product: {a * b}");
}
// Usage
OperationDelegate operationAdd = Add; // Assign the Add method to the delegate
OperationDelegate operationMultiply = Multiply; // Assign the Multiply method to the delegate
PerformOperation(3, 4, operationAdd); // Pass the delegate to the method
PerformOperation(3, 4, operationMultiply); // Pass the delegate to the method