What is Delegate? What is the use of Delegate?

  • Delegate is type that references to a method that has signature and parameter type same as delegate signature and parameter type.
  • Delegates are type safe function pointer.
  • Delegate declaration is same like a method declaration but without the body. 
  • Delegates allow functions to be passed as parameter to other functions.
  • using delegate keyword we can declare delegate type in C#.

See below example of delegate.

+
Code

using System;
 
namespace delegateSample
{
    public delegate float delCalculate(float a, float b);
 
    class Program
    {
        static void Main(string[] args)
        {
            float num1 = 10,num2 = 20;
 
            delCalculate delCalci = new delCalculate(delegateMethodDeclaration.add);
            delCalculate delCalci1 = new delCalculate(delegateMethodDeclaration.multiply);
 
            Console.WriteLine("Addition of 2 numbers = {0}", delCalci(num1,num2));
            Console.WriteLine("Multiplication of 2 numbers = {0}", delCalci1(num1, num2));
            Console.ReadLine();
        }
    }
 
    //New class declared
    public class delegateMethodDeclaration
    {
        public static float add (float firstNum,float secondNum)
        {
            return firstNum + secondNum;
        }
 
        public static float multiply(float firstNum,float secondNum)
        {
            return firstNum * secondNum;
        }
    }
}

We have declared delegate delCalculate with 2 float parameter and return type as float. So whatever function this delegate references should have 2 float parameters and its return type should be float. If we try to reference a function with diferent type of parameter and return type by using this delegate, then it will give compile time error. This shows that delegates are type safe function pointer.
In above sample we have 2 method declared with 2 float parameter and return type as float in delegateMethodDeclaration class and referenced and invoked these methods by using delegate object(Same like a class) in main method.

Now, you are wondering why we used delegate to call a method? We can directly call this method. Lets see what is the actual use of delegate by having some examples without using delegate and using delegate below.

Let us consider below simple example, where we have declared a class Numbers and a method called getAverage() which return average of all the numbers that we passed to it. Let us consider this Numbers class is in another assembly(dll) and we are using this dll in our program and calling function getAverage() in our main program (see below Code 1, I have called this method in our program class's main method.).


Code 1

+
Code
using System;
 
namespace withoutUsingDelegate
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] i = { 100, 5, 6, 7, 3, 1, 9, 8, 12, 13, 16, 17 };
            Numbers num = new Numbers(i);
            Console.WriteLine("Average of all numbers = {0}", num.getAverage(i));
            Console.ReadLine();
        }
    }
 
 
    //Number class created
    public class Numbers
    {
        int[] _numArr;
 
        public Numbers(int[] numArr)
        {
            _numArr = numArr;
        }
 
        public float getAverage(int[] numArr)
        {
            float total = 0;
            for (int i = 0; i < numArr.Length; i++)
            {
                total = total + numArr[i];
            }
            return total / numArr.Length;
        }
 
    }
 
}


Code 2

+
Code
using System;
 
namespace withoutUsingDelegate
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] i = { 100, 5, 6, 7, 3, 1, 9, 8, 12, 13, 16, 17 };
            Numbers num = new Numbers(i);
            Console.WriteLine("Average of all numbers = {0}", num.getAverage(i));
            Console.WriteLine("Average of all even numbers = {0}", num.getAverageOfEvenNumbers(i));
            Console.ReadLine();
        }
    }
 
 
    //Number class created
    public class Numbers
    {
        int[] _numArr;
 
        public Numbers(int[] numArr)
        {
            _numArr = numArr;
        }
 
        public float getAverage(int[] numArr)
        {
            float total = 0;
            for (int i = 0; i < numArr.Length; i++)
            {
                total = total + numArr[i];
            }
            return total / numArr.Length;
        }
 
        public float getAverageOfEvenNumbers(int[] numArr)
        {
 
            float total = 0;
            int evenNumbers = 0;
            for (int i = 0; i < numArr.Length; i++)
            {
                if (numArr[i] % 2 == 0)
                {
                    evenNumbers = evenNumbers + 1;
                    total = total + numArr[i];
                }
            }
            return total / evenNumbers;
        }
    }
}


Now suppose I want to calculate average of only even numbers from all the numbers that I passed. In order to do that I need to make change in my Numbers class. I can write a different function for that in my Numbers class or I will modify getAverage() function (See Code 2). But I want to make my Numbers class to be reusable. So instead of making changes in my Numbers class, I want users let implement logic from their end to do the functionality as per their requirement and pass it to my reusable function in Numbers class and here is actual delegate get comes into picture.

See the below example by using delegate for calculating average of all numbers and Even numbers.
 

+
Code
using System;
 
namespace Delegate_usage
{
    public delegate float delegategetAverage(int[] numbers);
    class Program
    {
        static void Main(string[] args)
        {
            int[] i = {100,5,6,7,3,1,9,8,12,13,16,17};
            Numbers num = new Numbers(i);
 
            delegategetAverage avgOfAllNum = new delegategetAverage(getAverage);
            Console.WriteLine("Average of All numbers = {0}", num.getAverageOfNum(avgOfAllNum));
 
            //calculating average of even numbers 
            delegategetAverage avgOfEvenNum = new delegategetAverage(getAverageOfEvenNumbers);
            Console.WriteLine("Average of Even numbers = {0}", num.getAverageOfNum(getAverageOfEvenNumbers));
            Console.ReadLine();
        }
 
        public static float getAverage(int [] numArr)
        {
            float total = 0;
            for (int i = 0; i < numArr.Length; i++)
            {
                total = total + numArr[i];
            }
            return total / numArr.Length;
        }
 
        public static float getAverageOfEvenNumbers(int [] numArr)
        {
            float total = 0;
            int evenNumbers = 0;
            for (int i = 0; i < numArr.Length; i++)
            {
                if (numArr[i] % 2 == 0)
                {
                    evenNumbers = evenNumbers + 1;
                    total = total + numArr[i];
                }
            }
            return total / evenNumbers;
        }
       
    }
 
    //Number class created
    public class Numbers
    {
        int[] _numArr;
 
        public Numbers(int[] numArr)
        {
            _numArr = numArr;
        }
 
        public float getAverageOfNum(delegategetAverage delAvg)
        {
            return delAvg(_numArr);
        }
    }
}

In the above example we have declared method getAverageOfNum() in our Numbers class which accept delegate as parameter. If a user want to calculate average of all the numbers then he simply create a method from their end which matches with delegate signatures. See in above example when I want to calculate average of all the numbers, I have created one function getAverage() at my side(client side) and passed this function to getAverageOfNum() as parameter with the help of delegate. Lets user of that class decide what functionality he want.

Similarly, when I want to calculate the average of even numbers then I have simply written and passed a function getAverageOfEvenNumbers() from my side using second delegate instance avgOfEvenNum. 
No need to make changes in our Numbers class.

Similarly, If you want to calculate the average of odd numbers, you can define the function at your end and pass it as parameter to function in Numbers class using another delegate instance.

This is one of simple example of delegate. If you check LINQ functions in dot net framework, you can see in most functions have heavy use of delegates. We will discuss more about LINQ in later chapter.

No comments :