A delegate(known as function pointer in C/C++) is a references type that invokes single/multiple method(s) through the delegate instance. It holds a reference of the methods. Delegate types are sealed and immutable type.
Types of Delegates
There are three types of delegates that can be used in C#.
Single Delegate
Multicast Delegate
Generic Delegate
Single Delegate
Single delegate can be used to invoke a single method. In the given source code example, a delegate CalculateSimpleInterest invokes a method getTotalInterest().
HideShrinkCopy Code
/// Sample example of simple delegate
///class Program
{
// Declare a delegatedelegatedouble CalculateSimpleInterest(double p, double t, double r);
static CalculateSimpleInterest SI = getTotalInterest;
staticvoid Main(string[] args)
{
double totalInterest;
//Method I : Invocation of simple delegate by using Invoke keyword
totalInterest = SI.Invoke(120, 1, 3.25);
Console.WriteLine("Total Interest of $120
in a year at rate of 3.25% APR is {0}",totalInterest);
//Method II : Invocation of simple delegate by passing method name
CalculateSimpleInterest D = new CalculateSimpleInterest(getTotalInterest);
totalInterest = D(120, 1, 3.25);
Console.WriteLine("Total Interest of $120
in a year at rate of 3.25% APR is {0}", totalInterest);
Console.ReadKey();
}
//Creating methods which will be assigned to delegate object///<summary>/// Gets the total interest.
///</summary>///<paramname="p"/>The Principal.
///<paramname="t"/>The Time.
///<paramname="r"/>The Rate.
///<returns>Total Interest
staticdouble getTotalInterest(double p, double t, double r)
{
return (p * t * r) / 100;
}
}
Multicast Delegate
Multicast delegate can be used to invoke the multiple methods. The delegate instance can do multicasting (adding new method on existing delegate instance) using the + operator and – operator can be used to remove a method from a delegate instance. All methods will invoke in sequence as they are assigned.
In the given source code example, a delegate instance dObjSI invokes the methods getTotalInterest(), getInterestRatePerYear() and getInterestTimeSpan().
HideShrinkCopy Code
///<summary>/// Sample example of multicast delegate
///class Program
{
// Declare a delegatedelegatedouble CalculateSimpleInterest(double para1, double para2, double para3);
static CalculateSimpleInterest dObjSI = getTotalInterest;
staticvoid Main(string[] args)
{
double SI;
//Calculating simple interest
SI = dObjSI.Invoke(120, 1, 3.25);
//using multicast delegate by invoking method getInterestRatePerYear()
dObjSI += new CalculateSimpleInterest(getInterestRatePerYear);
double Rate=dObjSI.Invoke(SI, 120, 1);
Console.WriteLine("APR rate is {0}", Rate);
//using multicast delegate by invoking method getInterestTimeSpan()
dObjSI += new CalculateSimpleInterest(getInterestTimeSpan);
double TimeSpan = dObjSI.Invoke(SI, 120, 3.25);
Console.WriteLine("Time Span is {0}", TimeSpan);
Console.ReadKey();
}
///<summary>/// Gets the total interest.
///</summary>///<paramname="p"/>The Principal.
///<paramname="t"/>The Time.
///<paramname="r"/>The Rate.
///<returns>Total Interest
staticdouble getTotalInterest(double p, double t, double r)
{
return (p * t * r) / 100;
}
///<summary>/// Gets the interest rate per year.
///</summary>///<paramname="SI"/>The Simple Interest.
///<paramname="p"/>The Principal.
///<paramname="t"/>The Time.
///<returns>Interest rate per year
staticdouble getInterestRatePerYear(double SI, double p, double t)
{
return (SI * 100)/(p*t);
}
///<summary>/// Gets the interest time span.
///</summary>///<paramname="SI"/>The Simple Interest.
///<paramname="p"/>The Principal.
///<paramname="r"/>The Rate.
///<returns>Interest time span
staticdouble getInterestTimeSpan(double SI, double p, double r)
{
return (SI * 100) / (p * r);
}
}
Generic Delegate
Generic Delegate was introduced in .NET 3.5 that don't require to define the delegate instance in order to invoke the methods.
There are three types of generic delegates:
Func
Action
Predicate
Generic Delegate: Func
The Func delegate defines a method that can be called on arguments and returns a result. In the given code example, delegate Func<interest,double> is defined with Interest type as argument and double as return type.
HideShrinkCopy Code
///<summary>/// Sample example of generic delegate
///class Program
{
// Declare a delegatedelegatedouble CalculateSimpleInterest(double para1, double para2, double para3);
static CalculateSimpleInterest dObjSI = getTotalInterest;
staticvoid Main(string[] args)
{
double SI;
//Declare a generic Func delegate
Func<interest,double> calcSI = SIObj =>(SIObj.P*SIObj.T*SIObj.R)/100;
Interest obj = new Interest();
obj.P = 120; obj.T = 1; obj.R = 3.25;
// Consuming delegate
SI = calcSI(obj);
Console.WriteLine("Total Interest of $120 in a year at rate of 3.25% APR is {0}", SI);
Console.ReadKey();
}
}
class Interest
{
publicdouble P { get; set; }
publicdouble T { get; set; }
publicdouble R { get; set; }
}
</interest,double>
Generic Delegate: Action
The Action delegate defines a method that can be called on arguments but does not return a result. In the given code example, delegate Action<string> is defined with string as argument.
HideCopy Code
Action<string> MyAction = y => Console.Write(y);
MyAction("Hello");
Console.ReadKey();
Generic Delegate: Predicate
The Predicate delegate defines a method that can be called on arguments and always returns Boolean type result. In the given code example, delegate Predicate<string> checkValidDate is defined with stringtype as argument and returns bool type.
HideCopy Code
///<summary>/// Sample example of generic delegate: Predicate
///class Program
{
staticvoid Main(string[] args)
{
string date="05/12/20143";
Predicate<string> checkValidDate = d => IsDate(d) ;
if (checkValidDate(date))
{
Console.WriteLine("Valid Date");
}
else
{
Console.WriteLine("Invalid Date");
}
Console.ReadKey();
}
privatestaticbool IsDate(string date)
{
DateTime dt;
return DateTime.TryParse(date,out dt);
}
}
</string>
Expression trees allow you to build code dynamically at runtime instead of statically typing it in the IDE and using a compiler. Expression Trees use generic delegates to create and parse the expressions.
Expression trees are used in the following cases:
Expression trees can be used to create LINQ to SQL and EF to SQL.
Expression trees can be used for ASP.NET MVC's HTML extensions.
Expression trees can be used to determine the selected property or field in MVC.
In the given code example, a expression (3+5)-(4-2) is divided into three expressions as Exp1 for (3+5), Exp2 for (4-2) and Exp3 for adding Exp1 and Exp2. The expression Expression.Lambda<func<int>>(resultexp).compile()() uses Func generic delegate to parse the expressions.
HideCopy Code
///<summary>/// Sample example of Expression Tree
///class Program
{
staticvoid Main(string[] args)
{
//Express tree (3+5)-(4-2)//3+5
BinaryExpression Exp1 = Expression.MakeBinary(ExpressionType.Add, Expression.Constant(3),
Expression.Constant(5));
//4-2
BinaryExpression Exp2 = Expression.MakeBinary(ExpressionType.Subtract, Expression.Constant(4),
Expression.Constant(2));
// (3+5)-(4-2)
BinaryExpression resultExp = Expression.MakeBinary(ExpressionType.Subtract, Exp1, Exp2);
//this stmt will create a delegates by parsing the expression threeint result = Expression.Lambda<func<int>>
(resultexp).compile()(); console.writeline("result="{0}",">
Difference Between Each Type of Generic Delegate
Func
Action
Predicate
Arguments
Yes
Yes
Yes
Returns
Yes
No
Boolean Type Only
--------------------------------------------------------------------------
In .net 3.5 some new generic delegates -Func<T>, Action<T> and Predicate<T> were introduced. Using generic delegates, it is possible to concise delegate type means you don’t have to define the delegate statement. These delegates are the Func<T>, Action<T> and Predicate<T> delegates and defined in the System namespace.
Action<T> performs an operation on the generic arguments. Func<T> performs an operationon the argument(s) and returns a value, and Predicate<T> is used to represent a set of criteria and determine if the argument matches the criteria.
delegate TResultFunc();
delegate TResultFunc(T arg);
delegate TResultFunc(T1 arg1, T2 arg2);
... up to T16
delegate voidAction();
delegate voidAction(T arg);
delegate voidAction(T1 arg1, T2 arg2);
... up to T16
Here "in" shows the input parameters and "out" shows the return value by the delegate.
Generic delegate example
usingSystem;
class demo
{
delegate voidMyDelegate(string str);
staticvoidMain(string[] args)
{
MyDelegate d = show;
d("Hello World!");
Console.ReadLine();
}
staticvoid show(string str)
{
Console.WriteLine(str);
}
}
Above code can be written as using generic delegate.
usingSystem;
class demo
{
staticvoidMain(string[] args)
{
Action<string> d = show;
d("Hello World!");
Console.ReadLine();
}
staticvoid show(string str)
{
Console.WriteLine(str);
}
}
Generic delegate using anonymous method
usingSystem;
class demo
{
staticvoidMain(string[] args)
{
Action<string> d = s =>Console.WriteLine(s);
d("Hello World!");
}
}
Func in C#:
We have learned in the previous section, that a delegates can be defined as shown below.
Example: C# Delegate
publicdelegateintSomeOperation(int i, int j);
classProgram
{
staticint Sum(int x, int y)
{
return x + y;
}
staticvoid Main(string[] args)
{
SomeOperation add = Sum;
int result = add(10, 10);
Console.WriteLine(result);
}
}
Output:
20
C# 3.0 includes built-in generic delegate types Func and Action, so that you don't need to define custom delegates as above.
Func is a generic delegate included in the System namespace. It has zero or more inputparameters and one out parameter. The last parameter is considered as an out parameter.
For example, a Func delegate that takes one input parameter and one out parameter is defined in the System namespace as below:
Func in C#:
namespace System
{
publicdelegate TResult Func<in T, out TResult>(T arg);
}
The last parameter in the angle brackets <> is considered as the return type and remaining parameters are considered as input parameter types as shown in the following figure.
Func delegate
A Func delegate with two input parameters and one out parameters will be represent as below.
Func delegate
The following Func type delegate is the same as the above SomeOperation delegate, where it takes two input parameters of int type and returns a value of int type:
C#:
Func<int, int, int> sum;
You can assign any method to the above func delegate that takes two int parameters and returns an int value. Now, you can take Func delegate instead of someOperation delegate in the first example.
Example: Func
classProgram
{
staticint Sum(int x, int y)
{
return x + y;
}
staticvoid Main(string[] args)
{
Func<int,int, int> add = Sum;
int result = add(10, 10);
Console.WriteLine(result);
}
}
Output:
20
A Func delegate type can include 0 to 16 input parameters of different types. However, it must include one out parameter for result. For example, the following func delegate doesn't have any input parameter, it includes only a out parameter.
Example: Func with zero input parameter
Func<int> getRandomNumber;
Func with an Anonymous method:
You can assign an anonymous method to the Func delegate by using the delegate keyword.
No comments:
Post a Comment