Creating and Using Simple Delegates in C# With a Program Example

Updated on November 30, 2018
sirama profile image

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

1. Introduction

“Delegate” is a reference type just like other normal csharp objects. When you create an object, the memory is allocated for the object on the heap and reference for it is stored in the reference variable, which is in the stack. Look at the below statement:

Organization Org = new Organization("ABC Inc.", staff1, 
staff2, staff3, staff4 );

Here, the organisation object is created on the Heap memory and a reference to that memory location is stored on the stack. The stack location is identified by the token Org. Like this Org reference, a delegate reference type will refer to a function's address. At run-time, the functions exposed by the source code will be loaded into a Code Segment of memory. If we take the starting address of a function (First line of translated code) in the Code segment and store it in a reference variable, we call that reference variable as a Delegate.

2. Declaring a Delegate

Below is the syntax for declaring a delegate:

Declaration of a Delegate
Declaration of a Delegate | Source

Once the delegate is declared, we can create the instance of the delegates. Just think about the class below:

class Publishers {}

The class keyword is used to specify the token Publishers as a class template. Later, we can create the object of template type Publishers. The same holds true for delegates. The above syntax shown us how to declare a delegate. Now, we will look at the below example of creating a Delegate:

public delegate int GetTotalDelegate(Staff[] staffs);

In the above declaration, we told that there is a delegate named GetTotalDelegate, which takes Array of Staff as a parameter and returns an integer to the caller. Later, we can create an instance of the delegate type GetTotalDelegate.

3. Creating a Delegate Reference

Now look at the below statement:

GetTotalDelegate Salary_Total = 
new GetTotalDelegate(Total_Salary );

In the above statement, we created the instance of delegate reference, Salary_Total. The type of the delegate is GetTotalDelegate. As we see, we are actually creating an object of type GetTotalDelegate. Now, go ahead and look at the syntax example once again. Got, the clue? Right.


As per the example, the compiler will actually create a class of type GetTotalDelegate and accepts any function name as a parameter in its constructor. But, the function must take an array of Staff as a parameter and return an integer. Here, Total_Salary is the name of the function we are passing in and that function takes an Array of Staff and returns an integer. Alright! Let us start our coding.

4. The Staff Class

This class is self-explanatory. It has field members, a constructor to initialize them and a ToString override. Below is the class:

//001: A class for Staff
public class Staff
{
	//001_1: Member variables
	private int StaffId;
	private string StaffName;
	public int Salary;
	public int Bonus;

	//001_2: Constructor for Staff
	public Staff(int id, string name, int Salary, 
        int bonus)
	{
		StaffId = id;
		StaffName = name;
		this.Salary = Salary;
		Bonus = bonus;
	}

	//001_3: String representation of staff
	public override string ToString()
	{
		return string.Format("{0} - {1}", 
            StaffName, StaffId);
	}
}

5. The Organization Class

This class has Array of staffs those forms the Organization.

1) First, we declare a delegate. The delegate name is GetTotalDelegate, and it takes an array of staff as a parameter and returns an integer. Below is the code:

//002: Oraganization has Staffs for its Operation
public class Organization
{
	//002_1: Delegate that Calculates 
    //and return the Total
	public delegate int 
        GetTotalDelegate(Staff[] staffs);

2) Next, we place two member variables in this class. One is Array of staff and another one is for Name of the Organization.

//002_2: Other member variables
private Staff[] Staffs;
private string Org_Name;

3) In the constructor we initialize the internal members. Constructor code is given below:

//002_3: Constructor for Organization
public Organization(string Org_name, params Staff[] staffs)
{
	//002_3.1: Initialize the Staffs Array
	Staffs = new Staff[staffs.Length];
	for(int i=0; i<staffs.Length; i++)
		Staffs[i] = staffs[i];

	//002_3.2: Initialize other member variables
	Org_Name = Org_name ;
}

4) The Calculate_Total function takes the delegate of type GetTotalDelegate as a parameter. Makes a call to the function referred by the delegate and returns the return value of the delegate parameter delegateRef. Note that when we are making a call with our delegate, the parameter passed in is a Staff array. The delegate returns an integer and the Calculate_Total function returns the same. Here, we do not bother what is implemented by the function that came as the parameter in the delegate’s form. Below is the Function that receives function as a parameter (Delegate) and returns an integer:

//002_4: Function that delegates the work 
//of Calculating Total
public int Calculate_Total(
  GetTotalDelegate delegateRef)
{
	return delegateRef(Staffs);
}

5) The DisplayStaffs function walks through the Staffs array and prints the staff object. Note, the ToString override is called as the Console.WriteLine tries to represent the Staff in string format. Below is the function:

//002_5: Diaplay all Staffs
public void DisplayStaffs()
{
	foreach(Staff staff in Staffs)
		Console.WriteLine(staff);
}

6. The Calculate Utility Class

If a class has all static functions in it, we will call it as a Utility Class. As all the members of the class are static, the clients need not create an instance and instead they can access the function by using the class name.

The Calculate class implements two functions. One function calculates Total salary and the other one calculates Total Bonus. Note, the function signature maps the delegate which we declared in the Organization class. This means, both the functions receive Staff Array as a parameter and return an integer. The Organization class delegate will use these functions and we will see that sooner. Below is the Utility Class:

//003: Utility Class for Making Calculation
public class Calculate
{
	//003_1: Helper function to Calculate 
    //Total Salary Expense
	public static int Total_Salary(
        Staff[] Staffs)
	{
		int sum = 0;
		foreach(Staff staff in Staffs)
			sum = sum + staff.Salary ;
		return sum;
	}
	
	//003_2: Helper function to Calculate Total 
    //Bonus for All Staffs
	public static int Total_Bonus(Staff[] Staffs)
	{
		int sum = 0;
		foreach(Staff staff in Staffs)
			sum = sum + staff.Bonus ;
		return sum;
	}
}

7. Delegate usage

Let us see how the user of the above classes uses the delegate. First, in the Main Program Entry, instances of four Staffs are created.

//Client 001: Create Staffs
Staff staff1 = new Staff(100, 
    "John Peterson", 100000, 10000);
Staff staff2 = new Staff(101, 
    "Mike Gold", 80000, 120000);
Staff staff3 = new Staff(102, 
    "Sundar Lal", 70000, 25000);
Staff staff4 = new Staff(103, 
    "Ervin Mooza", 50000, 27000);

Next, we create the Organization instance which receives all the staffs we created. The Organization class will copy staffs to its internal array member, Staffs.

//Client 002: Create Organization
Organization Org = new Organization
    ("ABC Inc.", staff1, staff2, 
    staff3, staff4 );
Org.DisplayStaffs();

Next, we create two delegate instances Salary_Total, Bonus_Total of the same type GetTotalDelegate. Note that for the constructor of this delegate, we are passing the function name which we created earlier in our Utility Class. These functions match the delegate by its arguments and its return type.

The Compiler, by reading the delegate keyword, defines a class called GetTotalDelegate. Well, that is behind the scenes of how the delegates work. But, one can use the ILDASM tool and by-part the class to have in-depth details.

//Client 003: Create the Delegates of same 
//type pointing to different function
Organization.GetTotalDelegate Salary_Total
    = new Organization.GetTotalDelegate(
    Calculate.Total_Salary );
Organization.GetTotalDelegate Bonus_Total 
    = new Organization.GetTotalDelegate(
    Calculate.Total_Bonus );

We calculate the total expense of organization by making a call to the Calculate_Total function. This function expects a delegate of type GetTotalDelegate as a parameter.

GetTotalDelegate is the wrapper class created by the compiler which our delegate function address. Calculate_Total function just makes a call to the function pointed by the GetTotalDelegate wrapper class and returns the Integer. We are making two calls to the Calculate_Total function. First time, we send Salary_Total function of our Utility Class and the second time; we send the Bonus_Total. The compiler-generated wrapper class takes care of calling the delegate functions. Finally, the output of these calls are gets printed in the console output window.

//Client 004: Now pass these delegates that
//is pointer to a function wrapped as a 
//class GetTotalDelegate 
//to the Organization class 
//member function.
int Total_Org_Expenses;
Total_Org_Expenses = Org.Calculate_Total(
    Salary_Total) + 
    Org.Calculate_Total(Bonus_Total);
Console.WriteLine("Total Expense  : " + 
    Total_Org_Expenses );

Complete Example and its output

using System;

namespace DelegatesP1
{
	//001: A class for Staff
	public class Staff
	{
		//001_1: Member variables
		private int StaffId;
		private string StaffName;
		public int Salary;
		public int Bonus;

		//001_2: Constructor for Staff
		public Staff(int id, string name, int Salary, 
            int bonus)
		{
			StaffId = id;
			StaffName = name;
			this.Salary = Salary;
			Bonus = bonus;
		}

		//001_3: String representation of staff
		public override string ToString()
		{
			return string.Format("{0} - {1}", 
                StaffName, StaffId);
		}
	}

	//002: Oraganization has Staffs for its Operation
	public class Organization
	{
		//002_1: Delegate that Calculates 
        //and return the Total
		public delegate int 
            GetTotalDelegate(Staff[] staffs);

		//002_2: Other member variables
		private Staff[] Staffs;
		private string Org_Name;

		//002_3: Constructor for Organization
		public Organization(string Org_name, 
            params Staff[] staffs)
		{
			//002_3.1: Initialize the Staffs Array
			Staffs = new Staff[staffs.Length];
			for(int i=0; i<staffs.Length; i++)
				Staffs[i] = staffs[i];

			//002_3.2: Initialize other 
            //member variables
			Org_Name = Org_name ;
		}

		//002_4: Function that delegates the 
        //work of Calculating Total
		public int Calculate_Total(
            GetTotalDelegate delegateRef)
		{
			return delegateRef(Staffs);
		}

        //002_5: Diaplay all Staffs
        public void DisplayStaffs()
        {
	        foreach(Staff staff in Staffs)
		        Console.WriteLine(staff);
        }

	}

    //003: Utility Class for Making Calculation
    public class Calculate
    {
	    //003_1: Helper function to Calculate 
        //Total Salary Expense
	    public static int Total_Salary(
            Staff[] Staffs)
	    {
		    int sum = 0;
		    foreach(Staff staff in Staffs)
			    sum = sum + staff.Salary ;
		    return sum;
	    }
    	
	    //003_2: Helper function to Calculate Total 
        //Bonus for All Staffs
	    public static int Total_Bonus(Staff[] Staffs)
	    {
		    int sum = 0;
		    foreach(Staff staff in Staffs)
			    sum = sum + staff.Bonus ;
		    return sum;
	    }
    }



	class Delegates1
	{
		[STAThread]
		static void Main(string[] args)
		{
            //Client 001: Create Staffs
            Staff staff1 = new Staff(100, 
                "John Peterson", 100000, 10000);
            Staff staff2 = new Staff(101, 
                "Mike Gold", 80000, 120000);
            Staff staff3 = new Staff(102, 
                "Sundar Lal", 70000, 25000);
            Staff staff4 = new Staff(103, 
                "Ervin Mooza", 50000, 27000);

            //Client 002: Create Organization
            Organization Org = new Organization
                ("ABC Inc.", staff1, staff2, 
                staff3, staff4 );
            Org.DisplayStaffs();

            //Client 003: Create the Delegates of same 
            //type pointing to different function
            Organization.GetTotalDelegate Salary_Total
                = new Organization.GetTotalDelegate(
                Calculate.Total_Salary );
            Organization.GetTotalDelegate Bonus_Total 
                = new Organization.GetTotalDelegate(
                Calculate.Total_Bonus );

            //Client 004: Now pass these delegates that
            //is pointer to a function wrapped as a 
            //class GetTotalDelegate 
            //to the Organization class 
            //member function.
            int Total_Org_Expenses;
            Total_Org_Expenses = Org.Calculate_Total(
                Salary_Total) + 
                Org.Calculate_Total(Bonus_Total);
            Console.WriteLine("Total Expense  : " + 
                Total_Org_Expenses );
		}
	}
}
CSharp Delegate Example - Output
CSharp Delegate Example - Output | Source

© 2018 sirama

Comments

    0 of 8192 characters used
    Post Comment

    No comments yet.

    working

    This website uses cookies

    As a user in the EEA, your approval is needed on a few things. To provide a better website experience, owlcation.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

    For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: https://owlcation.com/privacy-policy#gdpr

    Show Details
    Necessary
    HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
    LoginThis is necessary to sign in to the HubPages Service.
    Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
    AkismetThis is used to detect comment spam. (Privacy Policy)
    HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
    HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
    Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
    CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
    Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
    Features
    Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
    Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
    Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
    Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
    Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
    VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
    PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
    Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
    MavenThis supports the Maven widget and search functionality. (Privacy Policy)
    Marketing
    Google AdSenseThis is an ad network. (Privacy Policy)
    Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
    Index ExchangeThis is an ad network. (Privacy Policy)
    SovrnThis is an ad network. (Privacy Policy)
    Facebook AdsThis is an ad network. (Privacy Policy)
    Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
    AppNexusThis is an ad network. (Privacy Policy)
    OpenxThis is an ad network. (Privacy Policy)
    Rubicon ProjectThis is an ad network. (Privacy Policy)
    TripleLiftThis is an ad network. (Privacy Policy)
    Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
    Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
    Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
    Statistics
    Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
    ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
    Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)