In this article, we will look into the definition, declaration, instantiation and invocation of delegates.
Introduction
Delegates in C# allow the programmer to dynamically change the reference to the methods in a class. A delegate is a reference variable which holds the reference to a method. In procedural languages like C, there was a concept of pointers or memory references, even the hybrid C++ continued using the pointer concept. Pointers were omnipotent. A coder could reach every memory location using pointers, whether the memory stored variables, functions or any complex data structure. So we had a pointer to everything. Pointers helped a lot and led the way to system programming but it confused a little too. Particularly a misfired pointer could always bring damage to not only the program, the entire system too. Object Oriented programming concepts and the respective languages like Java or C# do not have the pointer concept any more but provides other structures (read ready made classes) which make the programmer’s job easier. In C# all the classes are reference type variables which allow you to create instances of objects and use them in different ways to meet your application’s requirements. Another such reference type is delegate, which hold reference to a method and allow you to change the reference at runtime. You can compare it with the “Pointer to a function” concept of C. The method can be activated at the occurrence of an event, where an event is associated with the delegate to call the method at runtime.
In this article, we will look into the definition, declaration, instantiation and invocation of delegates.
Using Delegates
Delegate declaration determines what kind of functions will be reference by the delegate. The delegate will refer to a method which has same signature as that of the delegate. C# provides for two types of delegates: single cast delegate and multicast delegate. A single cast delegate can call only one function. A multicast delegate as the name suggest can call more that one function. Multicast delegate refers to the head node of a linked list of functions.
The single cast delegate derives from the System.Delegate class whereas a multicast delegate derives from the System.MulticastDelegate class. Before going into the details of using a delegate, let us check the syntax for declaring and instantiating delegates.
The syntax and use of single cast delegate:
delegate <return type> <delegate_name><parameter_list>
For example:
public delegate Boolean Mydelegate(string s)
This delegate will be able to refer any function which will take a string as parameter and return a Boolean value. So the parameter type of the delegate and the return type of the referenced function must match with the parameter type and the return type of the single cast delegate.
To continue with our example, let us write a function:
public Boolean myfunction(string name)
{
Console.WriteLine(“Welcome ” + name);
return true;
}
Now we can create a Mydelegate object:
Mydelegate md = new Mydelegate(myfunction);
Next, we can call the delegate by giving the name of the delegate and by passing parameters, if required. It is similar to calling methods. a simple call like:
md(“James Joyce”);
will display ‘Welcome James Joyce’.
Another way of using a delegate is by passing the delegate as a parameter to a function. Now let us consider a situation where you have some information, which need to be logged into a file and at the same time displayed to the monitor (or any device/screen). So we will write two methods which will serve these two different purposes i.e., send the information to different destination. And we will create a delegate which will refer to both these methods.
The following program explains the concept:
using System;
using System.IO;
public class sendInfo
{
static FileStream fstream;
static StreamWriter swriter;
public delegate void sendinfo(string s);
//method sending information to screen:
public static void write_to_screen(string str)
{
Console.WriteLine("{0} Screen", str);
}
//method sending information to log file:
public static void write_to_log(string str)
{
fstream = new FileStream("d:\\logfile.txt", FileMode.Append, FileAccess.Write);
swriter = new StreamWriter(fstream);
str = str + " Logfile";
// writing to the file
swriter.WriteLine(str);
// flushing the buffer and closing the streams
swriter.Flush();
swriter.Close();
fstream.Close();
}
//this method will take the delegate as a parameter and send information to
// appropriate destination
public static void senddata(sendinfo si)
{
si("sending the Information to the");
}
public static void Main()
{
// initializing the delegate
sendinfo to_scr = new sendinfo(write_to_screen);
sendinfo to_file = new sendinfo(write_to_log);
senddata(to_scr);
senddata(to_file);
Console.ReadLine();
}
}
The syntax and use of multicast delegate:
A multicast delegate derives from the System.MulticastDelegate class. It contains an invocation list of multiple methods. In multicasting you create a single delegate that invokes multiple encapsulated methods. Return type of all these methods should be same. Declaration of a multicast delegate is same as that of a single cast delegate. Only difference is that, the return type of multicast delegate is always void. As multicast delegates refers to more than one method, when called it executes all the methods in the list in the calling order. The multiple methods called by the delegate in this way should not return any value because several methods are called consecutively and the application can not wait to get the return value from each of these methods.
In fact, when the delegate contains a return type of void, then it is automatically derived from the System.MulticastDelegate class and can held reference to multiple methods with a += operator. If the delegate contains a non-void return type then it is derived from the System.Delegate class and cannot support multiple methods.
In the above example the return type of the delegate was void, so it could hold reference to multiple methods, we could have rewritten the code as:
sendinfo si = new sendinfo(write_to_screen);
si += new sendinfo(write_to_log);
senddata(si);
si -= new sendinfo(write_to_file);
senddata(si);
Main use of delegates is with the events. In C# events use the publisher and subscriber model. An event is an action or occurrence such as mouse clicks, key presses, mouse movements or any system generated notification. The events are declared and raised in a class and associated with the event handlers using delegates within the same class or other classes. The class of which the event belongs is called the publisher class and is used to publish the events. Other classes can subscribe to these events. Consider the situations when more than one subscriber will have to be notified of an event. Keeping all these event handlers in a multicast delegate and firing it when the event occurs, simplifies the application. We will discuss use of delegates in event handling in details in our next article. At present let us look into the following code explains multicasting of delegates.
using System;
using System.IO;
class class1
{
public void display(string s)
{
Console.WriteLine("{0} from class 1 : ", s);
}
}
class class2
{
public void display(string s)
{
Console.WriteLine("{0} from class 2", s);
}
}
public delegate void display_message(string s);
class testmulticasting
{
public static void Main(string [] args)
{
class1 c1 = new class1();
class2 c2 = new class2();
// creating a delegate for displaying the message of class 1
display_message dm1 = new display_message(c1.display);
// creating a delegate for displaying the message of class 2
display_message dm2 = new display_message(c2.display);
display_message dm3;
// combining the two delegates using the Delegate.Combine method.
dm3=(display_message)Delegate.Combine(dm1,dm2);
Delegate [] dm4;
// Obtaining the array of delegate references by invoking GetInvocationList()
dm4 = dm3.GetInvocationList();
display_message dm5;
// navigating through the array and call each delegate which in turn would call each of the
// methods
for(int i=0;i< dm4.Length; i++)
{
// calling each of the delegates
dm5=(display_message)dm4[i];
dm5("This is");
}
}
}
Conclusion
In this article, I have discussed C# delegates, a very useful and highly used technique. In next article, you will see how delegates are used in event management.
About the Author
NAME: PIYALI SENGUPTA
QUALIFICATION: B.E., M.C.A
AREA OF INTEREST: WEB PROGRAMMING
HOBBIES: READING AND TRAVELLING
I HAVE MOSTLY WORKED AS A FACULTY. PRESENTLY WORKING FROM HOME.I LOVE MATHEMATICS, ALGORITHMS, PROGRAMMING, FRIENDS, CHILDREN AND NATURE NOT NECESSARILY IN THIS ORDER.YOU CAN CONTACT ME AT: itspiyali@gmail.com