Introduction
What are Delegates?
We all are familiar with the functions. We know that they perform a predefined set of work and return results based on arguments passed to them. For instances, a function AddOper(a,b) adds two numbers a and b and return the sum of these two numbers. Now think of writing a function which is versatile i.e. it is capable of performing a wide variety of tasks. Say it is capable of adding, subtracting and multiplying numbers.
One way of writing such a function would be to pass the type of operation we want to perform as argument along with the values on which we want to perform our operation. Example:AddOper(a,b,"add") for adding a and b. Inside the function we will be using the Select Case or if else statements for choosing the type of operation we want to perform. This approach is obviously complex and restrictive.
We want a very flexible and generic solution. We want to write a generic function called by the Main Application which in turn calls the appropriate function i.e. we are looking for something like this.
Now, the question is, is it possible to write such flexible Applications?
Yes, it is achievable if we pass a method to a method. Like GenericFun(AddOper). However, C# does not recommend this approach because of type safety reasons. Rather, C# has introduced a new object called DELEGATE for this purpose.
Like Class type, we define Delegate type and then create an instance of delegate to hold the details of a function, note that the instance only contains the details such as function signature and return type and not function body.
The syntax of declaring the delegate is as follows:
Public delegate int GenericFun(int a, int b);
Essentially, we are saying that delegate will accept functions whose return type is integer and which takes two arguments of type integers.
Now, lets say we want to work with addition function defines as follows:
Private int AddOper(int a,int b){}
Now, lets create an instance of this delegate and pass our add function to it. GenericFun? gfAdd=new GenericFun(AddOper);
So you see the constructor of a delegate takes the function name.
Now, lets see how we can pass this delegate to a generic function PrintResult? which can operate on any two numbers and returns an integer. Thus it can be used to print the result of Addition, subtraction, multiplication or any type of procedure which takes two integers and returns an integer. Currently, lets see how we can make PrintResult? to add two numbers.
int No1=40;
int No2=60;
PrintResult(gfAdd,No1,No2)
You will see 100 on the console.
Now we will see how PrintResult? method is defined.
Private int PrintResult(GenericFun action,int a,int b){
int result=action(a,b);
console.WriteLine(result);
}
so did you notice the magic! Just create an instance of delegate passing it the function you want to work with and then call your generic function passing it the delegate and you are done. To repeat the same exercise with subtraction function, we will do as follows:
GenericFun? gfSub=new GenericFun(SubOper);
PrintResult(gfSub,No1,No2);
However, it is possible to define an array of delegates, rather then defining each separate delegate. Thus we can also do the following:
GenericFun[] gf=new GenericFun(AddOper),
new GenericFun(SubOper),
Then to execute Subtract operation, use the following syntax:
PrintResult(gf1,No1,No2)
OK, Let me walk you through an example which uses Events, to see how delegates can be used with Events. Note that Events are a type of delegates.
To understand what delegates are and how they can be used, lets start with a simple scenario. A bank has a call center, which receives ATM card disputes. After the disputes are settled, the bank Rep sends the customer the outcome of the dispute in one of the following ways:
Email, if an email address is available by clicking SendEmail? button.
Fax, if fax number is available by clicking SendFax? button or
Letter, if email address or fax number is not available by clicking SendLetter? button.
So we need three event handlers to handle one of the following events:
SendEmailEvent? handler
SendFax? Handler,
SendLetter? handler.
We also need a Generic function that is called by the Main Application and which in turns calls appropriate Event Handler.
Lets start by writing three classes, which will be called Email, Fax and Letters respectively. Each class will have its own methods of sending Information. Therefore, Email class will have SendEmailMessage? method, Letter will have SendLetter? and Fax will have SendFax? methods for sending information.
Now, we need another class called MessageWatcher?, which is responsible for invoking the appropriate send method based on user's selection
We will also desigb a form with three buttons each for sending a particular type of message. Now when Rep clicks the SendEmailMessage? button, an event is generated, MessageWatcher? intercepts this event and calls the appropriate Event Handler. In this case the SendEmailMessage? method of Email class. Lets see how this can be done.
The MessageWatcher? class and the generic SendMessage? function is shown below.
public class MessageWatcher {
public delegate void MessageHandler(object Sender, MessageInfo mi);
public event MessageHandler OnMessageSendRequest;
public void SendMessage(MessageInfo mr) {
if (OnMessageSendRequest !=null)
OnMessageSendRequest(this,mr);
}
Notice that OnMessageSendRequest(this,mr) function is taking two arguments and does not return anything. Compare it with the SendEmailMessage? function as shown below.
public void SendEmailMessage(object Sender,MessageInfo? ei){}
It is extremely important that the signature of all the participating functions along with the generic function should have identical signature. Thus the signature of SendEmailMessage? and OnMessageSendRequest(this,mr) should have matching arguments and return type.
OK, so now the question is, how does MessageWatcher? class determines that it has to invoke the SendEmailMessage? handler? For this, first EmailClass? needs to notify the Watcher class that it will handle the SendEmail? event and it does this in its constructor. The syntax is as follows:
public Email(MessageWatcher mw){
watcher=mw;
watcher.OnMessageSendRequest+=new
MessageWatcher.MessageHandler(SendEmailMessage);
}
When the Email class is instantiated, it notifies the MessageWatcher? that when OnMessageSendRequest? event is raised, it will handle the event.
Did you notice that MessageHandler? is the delegate and we are simply passing it the function name SendEmailMessage?. So the Email class is essentially notifying the MessageWatcher? class that it will handle the SendEmailMessage? event.
Finally, in the main application we use these three lines.
//create an instance of email class
MessageWatcher mw=new MessageWatcher();
Email em=new Email(mw);mw.SendMessage(mi);
When the Rep clicks the SendEmailMessage? button, the Main Application create an instance of MessageWatcher? class and Email class. The Email constructor is passed the instance of watcher class. When Email class is instantiated, it notifies the MessageWatcher? instance that it will handle the event which in our case is SendEmailMessage?. Finally, the Main Application calls the generic SendMessage? function of the MessageWatcher? class passing it the MessageInfo? data structure.
The SendMessage? function MessageWatcher? class raises OnMessageSendRequest(this,mr) event and since the Email class has already notified the MessageWatcher? class that it will handle the SendEmailMessage? event therefore SendEmail? function is called to handle this event.
The Email class makes use of .NET System.Web classes for sending emails.
The Letter class makes use of Microsoft Word library. Since this library is a COM component thereforeI have used the System.Runtime.InteropServices. This class uses a template letter which has bookmarks for inserting texts for a customer.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.