In C#, a delegate is a type-safe reference to a method. It can be thought of as a pointer to a method. Delegates allow methods to be passed as parameters, and they enable flexible and dynamic method invocation. They are similar to function pointers in C and C++, but are type-safe and object-oriented in C#.
A delegate can point to a single method or multiple methods (in the case of multicast delegates).
To declare a delegate, we need to specify its signature, which includes the return type and parameters of the method it can reference. Here's a basic example:
public delegate void MyDelegate(string message); // Delegate declaration
In this case, MyDelegate is a delegate type that points to methods with the signature void MethodName(string message).
To create a delegate instance, we associate it with a method that matches its signature:
class Program
{
public static void PrintMessage(string message)
{
Console.WriteLine(message);
}
static void Main()
{
// Create a delegate instance pointing to PrintMessage method
MyDelegate del = new MyDelegate(PrintMessage);
// Invoke the delegate
del("Hello, World!"); // Output: Hello, World!
}
}
A multicast delegate is a delegate that can reference more than one method at the same time. When the multicast delegate is invoked, it calls each method in the list of methods in order, and passes the result from the last invoked method (in the case of void methods, they just execute in order without returning a value).
+= operator.-= operator.using System;
public delegate void MyDelegate(string message); // Delegate declaration
class Program
{
public static void Method1(string message)
{
Console.WriteLine("Method1: " + message);
}
public static void Method2(string message)
{
Console.WriteLine("Method2: " + message);
}
static void Main()
{
// Create a delegate instance
MyDelegate del = new MyDelegate(Method1);
// Add Method2 to the delegate invocation list
del += Method2;
// Invoke the delegate
del("Hello, Multicast!");
// Output:
// Method1: Hello, Multicast!
// Method2: Hello, Multicast!
}
}
In this example:
del points to Method1 initially.Method2 is added to the invocation list using the += operator.del("Hello, Multicast!")), it calls both Method1 and Method2.Order of Invocation: The methods are called in the order in which they are added to the delegate's invocation list.
Return Values: If the methods in the delegate have a return value, only the return value of the last method in the invocation list is returned. This is because the return value of a delegate invocation is overwritten with the return value of the last invoked method.
// Example with return values
public delegate int MyIntDelegate(int number);
public static int AddTen(int number) => number + 10;
public static int MultiplyByTwo(int number) => number * 2;
static void Main()
{
MyIntDelegate del = AddTen;
del += MultiplyByTwo;
// Only MultiplyByTwo's result (20) will be returned, because it is last
Console.WriteLine(del(5)); // Output: 20
}
Return Type of Multicast Delegates: For multicast delegates, the return type must be void if you expect all methods to execute without returning a value, as shown in the first multicast example. If the return type is non-void, only the result of the last method in the chain is returned.
Handling Exceptions: If an exception is thrown by one of the methods in a multicast delegate, the remaining methods will not be called. This can be managed by handling exceptions within each method.
If you no longer want to call a method, you can remove it from the multicast delegate using the -= operator:
del -= Method2; // Remove Method2 from the delegate
After removing Method2, if you invoke del, only Method1 will be called.
One of the most common uses of multicast delegates in C# is event handling. In event-driven programming, an event is often handled by multiple methods, and each handler can be added to a delegate (the event).
Here's a quick example of how a multicast delegate is used with events:
using System;
public delegate void Notify(); // Define a delegate for the event
public class EventPublisher
{
public event Notify OnNotify;
public void TriggerEvent()
{
OnNotify?.Invoke(); // Trigger the event (multicast delegate in action)
}
}
public class Subscriber
{
public void Handler1()
{
Console.WriteLine("Handler1 is called.");
}
public void Handler2()
{
Console.WriteLine("Handler2 is called.");
}
}
class Program
{
static void Main()
{
EventPublisher publisher = new EventPublisher();
Subscriber subscriber = new Subscriber();
// Subscribing methods to the event
publisher.OnNotify += subscriber.Handler1;
publisher.OnNotify += subscriber.Handler2;
// Trigger the event
publisher.TriggerEvent(); // Both handlers are called
// Output:
// Handler1 is called.
// Handler2 is called.
}
}
In this example:
OnNotify event uses a multicast delegate Notify.Handler1 and Handler2) are subscribed to the event.publisher.TriggerEvent()), both handlers are invoked.This powerful feature makes delegates and multicast delegates an essential part of C# programming, especially for event-driven applications.
Open this section to load past papers