Updated date:

Multicast Delegate in C# With Example

Author:

I am a software engineer. I have been working with C++, MFC, and .net technologies for 15 years. I like video games and reading books.

1. Introduction

In this article, we will see what is a “Multicast Delegate” and how we create and use it. Multicast delegates are the combination two or more delegates of same type and they together form a Delegate Chain. Each participant in the delegate chain should have a void return type.

In the code, we will take an example of an Order Processing System that makes use of the Multicast Delegate. First, we will create the OrderShipment Class and then we will move to the client code. In the client code, we will use our OrderShipment Class and Multicast Delegate.

2. OrderShipment Class

This Class breaks the order processing into a small group of functions. Moreover, all these functions will match a particular delegate type. This will make these functions eligible for delegate chaining.

1) First, we declare a simple delegate. Later, we will use this for the purpose delegate chaining. The delegate accepts Order Id and Customer Id as a parameter. Also, it returns nothing. Please keep in mind, multicast delegate principle work only for void return types. There is no restriction on the parameters it receives. Below is the Delegate declaration:

//001: OrderShipment class. Processes the order 
//placed by the customers
public class OrderShipment
{
	//001_1: Declare the Multi-cast delegate. 
  //Note the return type should be void
        public delegate void 
          OrderProcessingMethods(
          int OrderId, int CustomerId);

2) We split the order processing into five small functions. We will make these functions to form Delegate Chaining. The functions are shown below:

//001_2: Implement the Order Processing 
//Functions
//Processing Function 1
public void GetShoppingCartItems(int OrderId,
  int CustomerId)
{
	Console.WriteLine("(1) GetShoppingCartItems");
	Console.WriteLine("==================" + 
    "=============");
	Console.WriteLine("All shopping Cart Items" +
    " are Collected.");
	Console.WriteLine("Formed a Order with " +
    "supplied Orderid");
	Console.WriteLine("_____________________"+
    "_____________________________________"+
    "_____________");
}

//Processing Function 2
public void CalculateOrderPrice(int OrderId,
  int Customerid)
{
	Console.WriteLine("(2) CalculateOrderPrice");
	Console.WriteLine("=======================" +
    "========");
	Console.WriteLine("Price of each products " +
    "collected from the shopping " +
    "cart summed up");
	Console.WriteLine("Order Price calculated");
	Console.WriteLine("______________________" +
    "___________________________________" +
    "______________");
}

//Processing Function 3
public void CalculateDiscount(int OrderId, 
  int Customerid)
{
	Console.WriteLine("(3) CalculateDiscount");
	Console.WriteLine("======================" +
    "=========");
	Console.WriteLine("Get the Discount amount" +
  "for the VIP");
	Console.WriteLine("Reduce Order Price");
	Console.WriteLine("____________________" +
    "___________________________________" +
    "________________");
}

//Processing Function 4
public void AwordFreeGifts(int OrderId,
  int Customerid)
{
	Console.WriteLine("(4) AwordFreeGifts");
	Console.WriteLine("======================" +
    "=========");
	Console.WriteLine("Regular Customer. Pick " +
    "up a gift");
	Console.WriteLine("Place the gift item" +
    " in the Order for free");
	Console.WriteLine("_____________________" +
    "________________________________" +
    "__________________");
}

//Processing Function 5
public void GetOrderConfirmation(int OrderId, 
  int Customerid)
{
	Console.WriteLine("(5) GetOrderConfirmation");
	Console.WriteLine("======================" +
    "=========");
	Console.WriteLine("Order confirmation " +
    "screen shown to the User");
	Console.WriteLine("Order Confirmed");
	Console.WriteLine(".");
}

Note, in these functions, there is nothing more than the call to Console output. But, we obviously see, how these functions will be in real-world applications.

3) This class has a Member function that accepts the Multicast delegate as a parameter and then makes a call to it. The client will create the delegate chain based on the above five functions and then calls this Member function:

//001_3: Takes a multicase delegate and 
//performs business logic			
public void ProcessOrderShipment(
  OrderProcessingMethods ProcessToFollow, 
  int Orderid, int Customerid)
{
	ProcessToFollow(Orderid, Customerid);
}

We completed the Implementation of this class. Now, we will go for Delegate chaining.

3. Client Code - Delegate Chaining

The client will process the order shipment differently for three types of customers. The customer types are:

  1. Normal customers.
  2. Regular customers who makes purchases monthly twice or more.
  3. The VIP customer who has built up a good relation.

For Normal customer there is no discount and surprising gifts. The regular customer will have surprising gifts based on the order cost. And, VIP customer has a discount as well as gifts. Now, lets us go through how the client code makes use of the Multicast Delegates.

1) First, we create the instance of OrderShipment Class. Code is below:

//Client 001: Create Ordershipment Object
OrderShipment deliverorders = new OrderShipment();

2) Next, we declare a delegate of type OrderProcessingMethods. Later, we will use this delegate variable as a Multicast Delegate.

//Client 002: Declare the delegate. 
//We are going to use it as Multicast delegate
OrderShipment.OrderProcessingMethods orderprocess;

3) Next, we create five delegate instances and they point to one of the five methods implemented by the OrderShipment class.

//Client 003: Create Delegate Instances
OrderShipment.OrderProcessingMethods process1 = 
	new OrderShipment.OrderProcessingMethods
    (deliverorders.GetShoppingCartItems);
OrderShipment.OrderProcessingMethods process2 = 
	new OrderShipment.OrderProcessingMethods
    (deliverorders.CalculateOrderPrice);
OrderShipment.OrderProcessingMethods process3 = 
	new OrderShipment.OrderProcessingMethods
    (deliverorders.CalculateDiscount);
OrderShipment.OrderProcessingMethods process4 = 
	new OrderShipment.OrderProcessingMethods
    (deliverorders.AwordFreeGifts);
OrderShipment.OrderProcessingMethods process5 = 
	new OrderShipment.OrderProcessingMethods
    (deliverorders.GetOrderConfirmation);

4) Before processing the order for normal customer, a Delegate chain is formed by adding the Delegate created on the previous step. Once the individual delegates are combined using the + operator, we store the result in the orderprocess Delegate. Now, the orderprocess Delegate holds the chain of delegates which we call as a Multicast Delegate. We pass this Delegate Train to the OrderShipment class member function ProcessOrderShipment. When we call this function, the Delegate invokes all the functions currently in the chain. So, for the normal customer we do not want to provide a gift and/or discounts. Hence, those corresponding functions are not part of the Delegate chain. Also, note that the chained functions are called in the same order they are added to the chain. The chaining of function is shown below

Delegate Chaining

Delegate Chaining

The code we write to form this chain is below:

//Client 004: Process Order for Normal Customer. 
//Order Id: 1000. Customer id 1000.
Console.WriteLine("----------------------" +
    "------------------------------------------"+
    "-------------");
Console.WriteLine("Process Normal Customer");
Console.WriteLine("----------------------" +
    "------------------------------------------" +
    "-------------");
//Note you can use += operator also
orderprocess = process1 + process2 + process5; 
deliverorders.ProcessOrderShipment(orderprocess,
    1000,1000);

5) Next comes the VPI customer. As he is eligible for the gift as well as discounts, we need to add the corresponding functions to the multicast delegate orderprocess. Before we proceed, we should know the current delegates in the chain and also its placement. Process5 delegate is for order confirmation, which we should move to the last in the chain. So, process5 delegate removed from the chain, then process3 and process4 delegates are added to the chain. Finally, process5 delegate is put back before making the call to ProcessOrderShipment. Note the usage of the += operator. To add a delegate you can use += operator. And to remove a delegate from the chain, you can use -= operator.

//Client 005: Process Order for VIP Customer. 
//VIP eligible for Gift and discounts
//Order Id: 1001. Customer id 1001.
Console.WriteLine("----------------------" +
    "------------------------------------------" +
    "-------------");
Console.WriteLine("Process VIP Customer");
Console.WriteLine("----------------------" +
    "------------------------------------------" +
    "-------------");
//Remove Order confirmation from chain. 
//[It should be at location 5]
orderprocess -= process5;
//Add the Process 3 and 4
orderprocess += process3; 
orderprocess += process4;
//Put back the process 5. 
//Because order confirmation should be the last step.
orderprocess += process5; 
deliverorders.ProcessOrderShipment(orderprocess,
    1001,1001);

6) Now, we will re-arrange the chain for Regular Customer. We now know how delegate chaining works and hence no explanation is required. Below is the code:

//Client 006: Process Order for Regular customer. 
//Regular customer is not eligible for Gifts, 
//but enjoy discounts. 
//So revoke the gifting process
Console.WriteLine("----------------------" +
    "------------------------------------------" +
    "-------------");
Console.WriteLine("Process Regular Customer");
Console.WriteLine("----------------------" +
    "------------------------------------------" +
    "-------------");
orderprocess -= process4;
deliverorders.ProcessOrderShipment(orderprocess,
    1002,1002);

The complete code example and its output are given below:

using System;

namespace Delegates2
{
	class DelegatesP2
	{
		//001: OrderShipment class. Processes 
        //the order placed by the customers
		public class OrderShipment
		{
			//001_1: Declare the Multi-cast delegate. 
            //Note the return type should be void
            public delegate void 
                OrderProcessingMethods(int OrderId, 
                int CustomerId);

			//001_2: Implement the Order Processing Functions
			//Processing Function 1
			public void GetShoppingCartItems(int OrderId, 
                int CustomerId)
			{
				Console.WriteLine("(1) GetShoppingCartItems");
				Console.WriteLine("=======================" + 
                    "========");
				Console.WriteLine("All shopping Cart Items are " +
                    "Collected.");
				Console.WriteLine("Formed a Order with supplied " +
                    "Orderid");
				Console.WriteLine("______________________" + 
                    "____________________________________" + 
                    "_____________");
			}

			//Processing Function 2
			public void CalculateOrderPrice(int OrderId, 
                int Customerid)
			{
				Console.WriteLine("(2) CalculateOrderPrice");
                Console.WriteLine("=======================" +
                    "========");
				Console.WriteLine("Price of each products collected "+
                    "from the shopping cart summed up");
				Console.WriteLine("Order Price calculated");
                Console.WriteLine("______________________" +
                    "____________________________________" +
                    "_____________");
			}

			//Processing Function 3
			public void CalculateDiscount(int OrderId, 
                int Customerid)
			{
				Console.WriteLine("(3) CalculateDiscount");
                Console.WriteLine("=======================" +
                    "========");
				Console.WriteLine("Get the Discount amount for the VIP");
				Console.WriteLine("Reduce Order Price");
                Console.WriteLine("______________________" +
                    "____________________________________" +
                    "_____________");
			}

			//Processing Function 4
			public void AwordFreeGifts(int OrderId, 
                int Customerid)
			{
				Console.WriteLine("(4) AwordFreeGifts");
                Console.WriteLine("=======================" +
                    "========");
				Console.WriteLine("Regular Customer. Pick up a gift");
				Console.WriteLine("Place the gift item in the " +
                "Order for free");
                Console.WriteLine("______________________" +
                    "____________________________________" +
                    "_____________");
			}

			//Processing Function 5
			public void GetOrderConfirmation(int OrderId, 
                int Customerid)
			{
				Console.WriteLine("(5) GetOrderConfirmation");
                Console.WriteLine("=======================" +
                    "========");
				Console.WriteLine("Order confirmation screen" + 
                "shown to the User");
				Console.WriteLine("Order Confirmed");
				Console.WriteLine(".");
			}

			//001_3: Takes a multicase delegate and performs 
            //business logic			
			public void ProcessOrderShipment(
                OrderProcessingMethods ProcessToFollow, 
                int Orderid, int Customerid)
			{
				ProcessToFollow(Orderid, Customerid);
			}

		}
		[STAThread]
		static void Main(string[] args)
		{
            //Client 001: Create Ordershipment Object
            OrderShipment deliverorders = new OrderShipment();

            //Client 002: Declare the delegate. 
            //We are going to use it as Multicast delegate
            OrderShipment.OrderProcessingMethods orderprocess;

            //Client 003: Create Delegate Instances
            OrderShipment.OrderProcessingMethods process1 = 
	            new OrderShipment.OrderProcessingMethods
                (deliverorders.GetShoppingCartItems);
            OrderShipment.OrderProcessingMethods process2 = 
	            new OrderShipment.OrderProcessingMethods
                (deliverorders.CalculateOrderPrice);
            OrderShipment.OrderProcessingMethods process3 = 
	            new OrderShipment.OrderProcessingMethods
                (deliverorders.CalculateDiscount);
            OrderShipment.OrderProcessingMethods process4 = 
	            new OrderShipment.OrderProcessingMethods
                (deliverorders.AwordFreeGifts);
            OrderShipment.OrderProcessingMethods process5 = 
	            new OrderShipment.OrderProcessingMethods
                (deliverorders.GetOrderConfirmation);

            //Client 004: Process Order for Normal Customer. 
            //Order Id: 1000. Customer id 1000.
            Console.WriteLine("----------------------" +
                "------------------------------------------"+
                "-------------");
            Console.WriteLine("Process Normal Customer");
            Console.WriteLine("----------------------" +
                "------------------------------------------" +
                "-------------");
            //Note you can use += operator also
            orderprocess = process1 + process2 + process5; 
            deliverorders.ProcessOrderShipment(orderprocess,
                1000,1000);

            //Client 005: Process Order for VIP Customer. 
            //VIP eligible for Gift and discounts
            //Order Id: 1001. Customer id 1001.
            Console.WriteLine("----------------------" +
                "------------------------------------------" +
                "-------------");
            Console.WriteLine("Process VIP Customer");
            Console.WriteLine("----------------------" +
                "------------------------------------------" +
                "-------------");
            //Remove Order confirmation from chain. 
            //[It should be at location 5]
            orderprocess -= process5;
            //Add the Process 3 and 4
            orderprocess += process3; 
            orderprocess += process4;
            //Put back the process 5. 
            //Because order confirmation should be the last step.
            orderprocess += process5; 
            deliverorders.ProcessOrderShipment(orderprocess,
                1001,1001);

            //Client 006: Process Order for Regular customer. 
            //Regular customer is not eligible for Gifts, 
            //but enjoy discounts. 
            //So revoke the gifting process
            Console.WriteLine("----------------------" +
                "------------------------------------------" +
                "-------------");
            Console.WriteLine("Process Regular Customer");
            Console.WriteLine("----------------------" +
                "------------------------------------------" +
                "-------------");
            orderprocess -= process4;
            deliverorders.ProcessOrderShipment(orderprocess,
                1002,1002);
		}
	}
}

Output

Delegate Chaining Output

Delegate Chaining Output

© 2018 sirama