Delegates make it possible to programmatically
change method calls, and plug new codes in to existing classes. For these you
need to know what are the method matches delegate's signature and its return
type. Delegates are similar to C++ function pointers but delegates type safe and
Object Oriented. Methods don't need to match the delegate signature exactly.
What is Covariance and Contravariance in Delegates ?
Covariance and Contravariance provides kind of flexibility when matching the
method signature with delegate type that is defined.
Covariance permits a method to have a more derived return type than what is
defined when the delegate define. Contravariance permits a method to have less
derived parameter types than in the delegate type.
A delegate is a type; it encapsulates a method, see the below example:
// Define the Delegate
public
delegate void
TestDelegate(string
Message);
// Creating a method with string argument
public
static void
DisplayMessage(string Message)
{
Console.WriteLine(Message);
Console.ReadKey();
}
static void
Main(string[] args)
{
// Instantiate the delegate and encapsulates
the method "DisplayMessage"
TestDelegate
Test = DisplayMessage;
// call the delegate
Test("This is my delegate method");
}
This is a very simple example but delegates can be used in advance ways rather than this.
The instantiated delegate is an object, it can be passed as parameter, or assign
to a property. When a delegate is used in this way, the code used by the delegate
does not need any knowledge of the method being used. This is similar
functionality provide by interface encapsulation.
What is Multicasting?
In a delegate you can have more than one method to invoke, you can assign a method
to a delegate using "=" and you can add method a to a delegate where it has
assigned a method to invoke by using "+" if you want you can remove an assigned
method from a delegate where it has more methods to invoke by using "-". This is
called multicasting.
Multicasting example:
namespace
Delegates_Test2
{
delegate void
Del();
class
Simple
{
public void
MethodA()
{
System.Console.WriteLine("Message
from the method A.");
}
static public
void MethodB()
{
System.Console.WriteLine("Message
from the method B.");
}
}
}
namespace
Delegates_Test2
{
class
Program
{
static void
Main(string[] args)
{
Simple sc =
new Simple();
// Map delegate to
the method: A
Del
d = sc.MethodA;
// Map method: B
with multicasting
d += Simple.MethodB;
d(); // Both methods
are excute here
Console.ReadKey();
}
}
}
Generic Delegates
The delegate can define its own generic type parameters.
How to define:
public
delegate
void
MyDelegate<T>(T item);
Generic delegate example:
namespace
Generic_Delegate
{
//Generic Delegate define
here with return value of T, and both T arguments
public
delegate T
Calculator<T> (T arg1, T arg2);
class
MathUtility
{
// Generic method to
execute with Two generic argument values and one generic methods
public
static void
Calculate<T>(T[] values1, T[] values2, Calculator<T>
t)
{
for (int
i=0; i < values1.Length; i++)
{
values1[i] = t(values1[i],values2[i]);
// execute the T method with two of T
arguments
//And assigning results to First parameter
}
}
}
}
namespace
Generic_Delegate
{
class
Program
{
// My method to find
square value
static
int FindSquareValue(int
x, int y)
{
// Your method's
implementation
return
(x * y); // Your method have
defined to return the results
}
// My Method to find
dividence with first value by second value
static
double FindDividence(double
a, double b)
{
// Your method's
implementation
return
(a / b); // Your method have
defined to return the results
}
static void
Main(string[] args)
{
// To get Square
int[]
height = { 10, 5, 8 };
int[] width = { 4, 3, 6 };
MathUtility.Calculate(height,
width, FindSquareValue); //
Dynamically hook with FindSquare method
// You're only passing the both
values and method
Console.WriteLine("Display
Square Values...");
foreach (int
i in height)
{
Console.WriteLine(i.ToString());
}
// To get Dividence
double[]
Val1 = { 10, 80, 60 };
double[] val2 = {8,3,4};
MathUtility.Calculate(Val1, val2,
FindDividence);
Console.WriteLine("Display
Dividence values...");
foreach (double
d in Val1)
{
Console.WriteLine(d.ToString());
}
Console.ReadKey();
}
}
}