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.
“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:
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:
Once the delegate is declared, we can create the instance of the delegates. Just think about the class below:
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:
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:
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:
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:
2) Next, we place two member variables in this class. One is Array of staff and another one is for Name of the Organization.
3) In the constructor we initialize the internal members. Constructor code is given below:
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:
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:
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:
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.
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.
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.
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.
Complete Example and its output
© 2018 sirama