C# - Multi-Cast Delegate

In C#, a multi-cast delegate is like a list of instructions that can include more than one method. So, when you use this multi-cast delegate, it carries out several methods, one after the other, in the sequence they were added. It's worth noting that every delegate in C# has the capability to be a multicast delegate due to the presence of the Combine and Remove methods inherited from the System.Delegate class.

The += operator is used to chain together (combine) delegate instances, and the -= operator is used to remove a delegate reference.

Example:

Let's demonstrate the concept with a simple example:


using System;

// Declare a delegate
public delegate void SimpleDelegate();

public class Program
{
    public static void Main()
    {
        SimpleDelegate del1 = Method1;
        SimpleDelegate del2 = Method2;
        
        // Creating a multi-cast delegate
        SimpleDelegate multiCast = del1 + del2;

        Console.WriteLine("Invoking the multi-cast delegate:");
        multiCast();  // Outputs: Method1 invoked! followed by Method2 invoked!

        // Removing a delegate
        multiCast -= del1;
        Console.WriteLine("\nAfter removing del1:");
        multiCast();  // Outputs: Method2 invoked!
    }

    public static void Method1()
    {
        Console.WriteLine("Method1 invoked!");
    }

    public static void Method2()
    {
        Console.WriteLine("Method2 invoked!");
    }
}

Output


Invoking the multi-cast delegate:
Method1 invoked!
Method2 invoked!

After removing del1:
Method2 invoked!

In the example:

  • We have a delegate called SimpleDelegate that matches methods with a void return type and no parameters.
  • We assign Method1 to del1 and Method2 to del2.
  • We then create a multi-cast delegate, multiCast, by combining del1 and del2 using the + operator.
  • When we invoke multiCast, both Method1 and Method2 are called in the order they were added.
  • We then demonstrate removing a delegate from the multi-cast delegate using the -= operator. After removing del1, only Method2 is invoked when multiCast is called.

Linking methods like this gives you flexibility in how you use and call them. But, it's crucial to be careful with multi-cast delegates, especially when dealing with what they return and how they might affect other parts of the program. This helps prevent unexpected things from happening.

Multi-cast Delegate Real-time Example:

In the real world, multi-cast delegates can be handy in event-based programming, like in interfaces or when we need to inform many people about something happening.

Scenario:

Imagine you have an alarm system. Multiple people are subscribed and they want to be alerted when the alarm is triggered. For instance:

  1. A buzzer sounds.
  2. The lights flash.
  3. A notification is sent to the security agency.

All of these actions need to be invoked when the alarm is triggered. This is a perfect situation for a multicast delegate because multiple methods (sounding the buzzer, flashing the lights, sending a notification) need to be called on a single event (alarm triggered).

Example:


using System;

public class Alarm
{
    public delegate void AlarmHandler();
    public event AlarmHandler OnAlarmTriggered;

    public void Trigger()
    {
        Console.WriteLine("Alarm has been triggered!");
        OnAlarmTriggered?.Invoke();
    }
}

public class Program
{
    static void Main()
    {
        Alarm alarm = new Alarm();

        // Subscribe to the alarm event
        alarm.OnAlarmTriggered += SoundBuzzer;
        alarm.OnAlarmTriggered += FlashLights;
        alarm.OnAlarmTriggered += NotifySecurity;

        alarm.Trigger();
    }

    static void SoundBuzzer()
    {
        Console.WriteLine("Buzzer sounding loudly...");
    }

    static void FlashLights()
    {
        Console.WriteLine("Lights are flashing...");
    }

    static void NotifySecurity()
    {
        Console.WriteLine("Notifying the security agency...");
    }
}

The output of the program will be:


Alarm has been triggered!
Buzzer sounding loudly...
Lights are flashing...
Notifying the security agency...
Explanation:
  1. An instance of the Alarm class is created.
  2. Three methods (SoundBuzzer, FlashLights, NotifySecurity) are subscribed to the OnAlarmTriggered event.
  3. The Trigger method is called on the Alarm instance.
    • First, it prints "Alarm has been triggered!".
    • Then, it invokes all the methods that are subscribed to the OnAlarmTriggered event, one by one.

The methods are invoked in the order they were added to the event delegate, resulting in the output specified above.

This is a multicast delegate in action. As in the example, the OnAlarmTriggered event holds references to multiple methods and when the event is triggered, this invokes them in the order they were added.

It's a simple example but demonstrates how you can use multicast delegates to notify multiple subscribers or perform multiple actions based on a single event or condition.

Points to Remember:
  1. Definition: A multi-cast delegate can hold references to more than one method. This enables the delegate to invoke multiple methods in sequence when it's called.
  2. Combine & Remove: You can combine delegate instances using the += operator and remove them using the -= operator. These operations manipulate the invocation list of the delegate.
  3. Invocation Order: Methods are invoked in the order they are added to the delegate's invocation list.
  4. Return Values: If the delegate has a return type other than void, only the value from the last invoked method is returned. The other return values are discarded.
  5. Delegate.Combine and Delegate.Remove: Besides the += and -= operators, you can also use the static methods Delegate.Combine and Delegate.Remove to manage the invocation list.
  6. Invocation List: You can access the array of delegate instances (methods) that a multi-cast delegate refers to using the GetInvocationList method.
  7. Exceptions: If one of the methods in the invocation list throws an exception, the execution of subsequent methods in the list will be halted.
  8. Null Delegates: A multi-cast delegate can be null, indicating it has no methods in its invocation list. Always check for null before invoking a delegate.
  9. Type Safety: Multi-cast delegates are type-safe. They can only hold references to methods that match their declared signature.
  10. Memory Considerations: Holding long-lived references to methods in a multi-cast delegate can prevent garbage collection of the objects owning those methods. This can lead to memory leaks if not managed carefully.
  11. Usage Scenarios: Multi-cast delegates are often used in event-driven programming in C#, where multiple subscribers (methods) might want to react to a single event.
  12. Immutable Nature: Delegates, including multi-cast delegates, are immutable. This means that when you modify a delegate (using += or -=), you get a new delegate instance rather than modifying the original one.