c# delegates are similar to pointers to functions, in c or c++. a delegate is a reference type variable that holds the reference to a method. the reference can be changed at runtime.
delegates are especially used for implementing events and the call-back methods. all delegates are implicitly derived from the system.delegate class.
declaring delegates
delegate declaration determines the methods that can be referenced by the delegate. a delegate can refer to a method, which has the same signature as that of the delegate.
for example, consider a delegate −
public delegate int mydelegate (string s);
the preceding delegate can be used to reference any method that has a single string parameter and returns an int type variable.
syntax for delegate declaration is −
delegate <return type> <delegate-name> <parameter list>
instantiating delegates
once a delegate type is declared, a delegate object must be created with the new keyword and be associated with a particular method. when creating a delegate, the argument passed to the new expression is written similar to a method call, but without the arguments to the method. for example −
public delegate void printstring(string s); ... printstring ps1 = new printstring(writetoscreen); printstring ps2 = new printstring(writetofile);
following example demonstrates declaration, instantiation, and use of a delegate that can be used to reference methods that take an integer parameter and returns an integer value.
using system;
delegate int numberchanger(int n);
namespace delegateappl {
class testdelegate {
static int num = 10;
public static int addnum(int p) {
num += p;
return num;
}
public static int multnum(int q) {
num *= q;
return num;
}
public static int getnum() {
return num;
}
static void main(string[] args) {
//create delegate instances
numberchanger nc1 = new numberchanger(addnum);
numberchanger nc2 = new numberchanger(multnum);
//calling the methods using the delegate objects
nc1(25);
console.writeline("value of num: {0}", getnum());
nc2(5);
console.writeline("value of num: {0}", getnum());
console.readkey();
}
}
}
when the above code is compiled and executed, it produces the following result −
value of num: 35 value of num: 175
multicasting of a delegate
delegate objects can be composed using the "+" operator. a composed delegate calls the two delegates it was composed from. only delegates of the same type can be composed. the "-" operator can be used to remove a component delegate from a composed delegate.
using this property of delegates you can create an invocation list of methods that will be called when a delegate is invoked. this is called multicasting of a delegate. the following program demonstrates multicasting of a delegate −
using system;
delegate int numberchanger(int n);
namespace delegateappl {
class testdelegate {
static int num = 10;
public static int addnum(int p) {
num += p;
return num;
}
public static int multnum(int q) {
num *= q;
return num;
}
public static int getnum() {
return num;
}
static void main(string[] args) {
//create delegate instances
numberchanger nc;
numberchanger nc1 = new numberchanger(addnum);
numberchanger nc2 = new numberchanger(multnum);
nc = nc1;
nc += nc2;
//calling multicast
nc(5);
console.writeline("value of num: {0}", getnum());
console.readkey();
}
}
}
when the above code is compiled and executed, it produces the following result −
value of num: 75
using delegates
the following example demonstrates the use of delegate. the delegate printstring can be used to reference method that takes a string as input and returns nothing.
we use this delegate to call two methods, the first prints the string to the console, and the second one prints it to a file −
using system;
using system.io;
namespace delegateappl {
class printstring {
static filestream fs;
static streamwriter sw;
// delegate declaration
public delegate void printstring(string s);
// this method prints to the console
public static void writetoscreen(string str) {
console.writeline("the string is: {0}", str);
}
//this method prints to a file
public static void writetofile(string s) {
fs = new filestream("c:\\message.txt",
filemode.append, fileaccess.write);
sw = new streamwriter(fs);
sw.writeline(s);
sw.flush();
sw.close();
fs.close();
}
// this method takes the delegate as parameter and uses it to
// call the methods as required
public static void sendstring(printstring ps) {
ps("hello world");
}
static void main(string[] args) {
printstring ps1 = new printstring(writetoscreen);
printstring ps2 = new printstring(writetofile);
sendstring(ps1);
sendstring(ps2);
console.readkey();
}
}
}
when the above code is compiled and executed, it produces the following result −
the string is: hello world