Delegates
Delegates
Purpose of this post is to take baby steps towards understanding delegates in .Net by using simple example and gradually proceed to more complex scenarios.
Definition
A delegate in C# is
similar to a function pointer in C or C++. Using a delegate allows the
programmer to encapsulate a reference to a method inside a delegate object. The
delegate object can then be passed to code which can call the referenced
method, without having to know at compile time which method will be invoked.
Unlike function pointers in C or C++, delegates are object-oriented, type-safe,
and secure. [msdn]
Where to use Delegates
If we look at the prime
use of delegates its mostly used for implementing events and the call-back
methods.
Which Namespace has them
All delegates are
implicitly derived from the System.Delegate class.
Types of Delegates
Delegates are three types:
- Single Delegate
- Multicast Delegate
- Generic Delegate
Single Delegate
Understand Single Delegate with simple example
Perform following steps
to get up to a point where you have the program set up before we dive deep and
understand what is happening:
- Make a console project in Visual
Studio
- In the default
project add a new class SimpleCalculator.cs, use the following code
/// <summary>
/// Simple
Calculator performing Addition, Subtraction, Multiplication and Division
///
</summary>
public
class SimpleCalculator
{
/// <summary>
/// Add Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Addition of num1 and num2</returns>
public static int Add(int num1,int num2)
{
return num1 + num2;
}
/// <summary>
/// Subtract Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Substration of num1 and num2</returns>
public static int Subtract(int num1, int num2)
{
return num1 - num2;
}
/// <summary>
/// Multiply Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Multiplication of num1 and num2</returns>
public static int Multiply(int num1, int num2)
{
return num1 * num2;
}
/// <summary>
/// Divide Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Division of num1 and num2</returns>
public static int Divide(int num1, int num2)
{
return num1 / num2;
}
}
- Replace your program.cs class code
with following code:
class Program
{
delegate int SimpleCalculatorDelegate(int num1,int num2);
static void Main(string[] args)
{
Single();
}
static void Single()
{
var scdAdd = new SimpleCalculatorDelegate(SimpleCalculator.Add);
var scdSubtract = new SimpleCalculatorDelegate(SimpleCalculator.Subtract);
var scdMultiply = new SimpleCalculatorDelegate(SimpleCalculator.Multiply);
var scdDivide = new SimpleCalculatorDelegate(SimpleCalculator.Divide);
int num1 = 10;
int num2 = 5;
Console.WriteLine("Running Calculations with Single delegate using {0},{1}: ", num1, num2);
Console.WriteLine("Add({0}+{1}): {2}", num1, num2, scdAdd(num1, num2));
Console.WriteLine("Subtract({0}-{1}): {2}", num1, num2, scdSubtract(num1, num2));
Console.WriteLine("Multiply({0}*{1}): {2}", num1, num2, scdMultiply(num1, num2));
Console.WriteLine("Divide({0}/{1}): {2}", num1, num2, scdDivide(num1, num2));
Console.ReadLine();
}
static void Single()
{
var scdAdd = new SimpleCalculatorDelegate(SimpleCalculator.Add);
var scdSubtract = new SimpleCalculatorDelegate(SimpleCalculator.Subtract);
var scdMultiply = new SimpleCalculatorDelegate(SimpleCalculator.Multiply);
var scdDivide = new SimpleCalculatorDelegate(SimpleCalculator.Divide);
int num1 = 10;
int num2 = 5;
Console.WriteLine("Running Calculations with Single delegate using {0},{1}: ", num1, num2);
Console.WriteLine("Add({0}+{1}): {2}", num1, num2, scdAdd(num1, num2));
Console.WriteLine("Subtract({0}-{1}): {2}", num1, num2, scdSubtract(num1, num2));
Console.WriteLine("Multiply({0}*{1}): {2}", num1, num2, scdMultiply(num1, num2));
Console.WriteLine("Divide({0}/{1}): {2}", num1, num2, scdDivide(num1, num2));
Console.ReadLine();
}
}
- You project should be building
fine at this point if you have any problems compiling your code leave me a
message I will get back to you as soon as possible.
- Running the application will
produce the following output:
Explanation
Single delegate can only invoke a single method in one call simply putting SimpleCalculatorDelegate can only invoke Add or Delete or Multiply or Divide in one call.
Above example has a simple class with simple methods defined in that, purpose SimpleCalculator class is to perform calculations nothing more is expected from that. Two numbers are passed to all the methods defined in the class and in return you get one number back as a result.
Above example has a simple class with simple methods defined in that, purpose SimpleCalculator class is to perform calculations nothing more is expected from that. Two numbers are passed to all the methods defined in the class and in return you get one number back as a result.
By now we started to note
some symmetry building up there, each method has two arguments and one result;
pretty straight forward up to this point.
As we know in simple words
delegate is a representative and its job is to represent something. C# delegate
has some structure assigned to it.
Lets try to find the
structure so that we can make sense out of it:
- Delegate should have same number
of arguments as the function we are trying to encapsulate.
- Delegate should have same return
type as the function we are trying to encapsulate.
In our case we defined:
delegate
int SimpleCalculatorDelegate(int num1,int num2);
which is
exactly same in signature as:
int Add(int num1,int
num2)
int Subtract(int num1,
int num2)
int Multiply(int num1,
int num2)
int Divide(int num1, int
num2)
One note to make here is
your method or function can be Static or NonStatic, delegate has no problem
representing it.
Next we will see the
declaration part of it:
var scdAdd
= new SimpleCalculatorDelegate(SimpleCalculator.Add);
var
scdSubtract = new SimpleCalculatorDelegate(SimpleCalculator.Subtract);
var
scdMultiply = new SimpleCalculatorDelegate(SimpleCalculator.Multiply);
var
scdDivide = new SimpleCalculatorDelegate(SimpleCalculator.Divide);
Here we created object of
our delegate and passed in the method we want it to represent, since method and
delegate have similar signature; delegate will represent the method happily!
Next we will see the usage
part of it or calling part of it:
Console.WriteLine("Add({0}+{1}):
{2}", num1, num2, scdAdd(num1, num2));
Console.WriteLine("Subtract({0}-{1}):
{2}", num1, num2, scdSubtract(num1, num2));
Console.WriteLine("Multiply({0}*{1}):
{2}", num1, num2, scdMultiply(num1, num2));
Console.WriteLine("Divide({0}/{1}):
{2}", num1, num2, scdDivide(num1, num2));
When we defined our
delegate objects and passed methods to represent to it delegate know in which
object which method it is representing. So when we say scdAdd(num1, num2) it will call the Add method and
pass on the arguments and receive the output and pass it back.
By so far I have made an attempt to explain a delegate in easiest way I can.
--------------------------------------------------------------------------------------------------------------------------
Multicast Delegate
Understand Multicast Delegate with simple example
Perform following steps to get up to a point where you have the program set up before we dive deep and understand what is happening:
- Make a console project in Visual Studio
- In the default project add a new class SimpleCalculator.cs, use the following code
/// <summary>
/// Simple Calculator performing Addition, Subtraction, Multiplication and Division
/// </summary>
public class SimpleCalculator
{
/// <summary>
/// Add Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Addition of num1 and num2</returns>
public static int Add(int num1,int num2)
{
return num1 + num2;
}
/// <summary>
/// Subtract Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Substration of num1 and num2</returns>
public static int Subtract(int num1, int num2)
{
return num1 - num2;
}
/// <summary>
/// Multiply Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Multiplication of num1 and num2</returns>
public static int Multiply(int num1, int num2)
{
return num1 * num2;
}
/// <summary>
/// Divide Numbers
/// </summary>
/// <param name="num1">Number 1</param>
/// <param name="num2">Number 2</param>
/// <returns>Division of num1 and num2</returns>
public static int Divide(int num1, int num2)
{
return num1 / num2;
}
}
- Replace your program.cs class code with following code:
class Program
private static void Multicast()
{
var scdAdd = new SimpleCalculatorDelegate(SimpleCalculator.Add);
var scdSubtract = new SimpleCalculatorDelegate(SimpleCalculator.Subtract);
var scdMultiply = new SimpleCalculatorDelegate(SimpleCalculator.Multiply);
var scdDivide = new SimpleCalculatorDelegate(SimpleCalculator.Divide);
int num1 = 10;
int num2 = 5;
var scdAddSubtract = (SimpleCalculatorDelegate)Delegate.Combine(scdAdd, scdSubtract);
var scdMultiplyDivide = (SimpleCalculatorDelegate)Delegate.Combine(scdMultiply, scdDivide);
Console.WriteLine("\r\nRunning Calculations with Multicast delegate(Using Simple Invoke) using {0},{1}: ", num1, num2);
Console.WriteLine("Run Add and Subtract with {0},{1}: {2}", num1, num2, scdAddSubtract(num1,num2));
Console.WriteLine("Run Multiply and Divide with {0},{1}: {2}", num1, num2, scdMultiplyDivide(num1, num2));
Console.Write("\r\nRunning Calculations with Multicast delegate(Using Invocation List) using {0},{1}: ", num1, num2);
Console.Write("Run Add and Subtract with {0},{1}: ", num1, num2);
scdAddSubtract.GetInvocationList().Select(x => (int)x.DynamicInvoke(num1, num2)).ToList().ForEach(x => Console.Write(" " + x + " "));
Console.Write("\r\nRun Multiply and Divide with {0},{1}: ", num1, num2);
scdMultiplyDivide.GetInvocationList().Select(x => (int)x.DynamicInvoke(num1, num2)).ToList().ForEach(x => Console.Write(" " + x + " "));
Console.ReadLine();
}
}
{
delegate int SimpleCalculatorDelegate(int num1,int num2);
static void Main(string[] args)
{
Multicast();
}
{
var scdAdd = new SimpleCalculatorDelegate(SimpleCalculator.Add);
var scdSubtract = new SimpleCalculatorDelegate(SimpleCalculator.Subtract);
var scdMultiply = new SimpleCalculatorDelegate(SimpleCalculator.Multiply);
var scdDivide = new SimpleCalculatorDelegate(SimpleCalculator.Divide);
int num1 = 10;
int num2 = 5;
var scdAddSubtract = (SimpleCalculatorDelegate)Delegate.Combine(scdAdd, scdSubtract);
var scdMultiplyDivide = (SimpleCalculatorDelegate)Delegate.Combine(scdMultiply, scdDivide);
Console.WriteLine("\r\nRunning Calculations with Multicast delegate(Using Simple Invoke) using {0},{1}: ", num1, num2);
Console.WriteLine("Run Add and Subtract with {0},{1}: {2}", num1, num2, scdAddSubtract(num1,num2));
Console.WriteLine("Run Multiply and Divide with {0},{1}: {2}", num1, num2, scdMultiplyDivide(num1, num2));
Console.Write("\r\nRunning Calculations with Multicast delegate(Using Invocation List) using {0},{1}: ", num1, num2);
Console.Write("Run Add and Subtract with {0},{1}: ", num1, num2);
scdAddSubtract.GetInvocationList().Select(x => (int)x.DynamicInvoke(num1, num2)).ToList().ForEach(x => Console.Write(" " + x + " "));
Console.Write("\r\nRun Multiply and Divide with {0},{1}: ", num1, num2);
scdMultiplyDivide.GetInvocationList().Select(x => (int)x.DynamicInvoke(num1, num2)).ToList().ForEach(x => Console.Write(" " + x + " "));
Console.ReadLine();
}
}
- You project should be building fine at this point if you have any problems compiling your code leave me a message I will get back to you as soon as possible.
- Running the application will produce the following output:
Explanation
With multicast delegate you can combine functionality of more than one delegates.
var scdAddSubtract = (SimpleCalculatorDelegate)Delegate.Combine(scdAdd, scdSubtract);
scdAddSubrtact has combined scdAdd and acdSubtract i.e. calling scdAddSubrtact will run both of them. You need to use invocation list as shown above if you want the data from all the subdelegates else you will only get the data from the one which executed the last. Please refer to the code and output above.
--------------------------------------------------------------------------------------------------------------------------
Generic Delegate
Understand Generic Delegate with simple example
Work in Progress, please check back later
Comments
Post a Comment