- 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.
+
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
+
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
+
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.
+
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.