C# Delegate
Delegates in C# are similar to function pointers in C or C++. A delegate is a reference type variable that holds a reference to a method. The reference can be changed at runtime.
Delegates are especially used for implementing events and callback methods. All delegates derive from the System.Delegate class.
Declaring a Delegate
A delegate declaration determines the methods that can be referenced by the delegate. A delegate can point to a method that has the same signature as it does.
For example, suppose you have a delegate:
public delegate int MyDelegate(string s);
This delegate can be used to reference any method that takes a single string parameter and returns an int type variable.
The syntax for declaring a delegate is as follows:
delegate <return type> <delegate-name> <parameter list>
Instantiating a Delegate
Once a delegate type is declared, a delegate object must be created using the new keyword and associated with a specific method. When creating a delegate, the arguments passed to the new statement are written as if they were a method call, but without the parameters. For example:
public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
The following example demonstrates the declaration, instantiation, and use of a delegate that can reference a method taking an integer parameter and returning an integer value.
Example
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);
// Use delegate objects to call methods
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 combined using the "+" operator. A combined delegate calls the two delegates it was combined from. Only delegates of the same type can be combined. The "-" operator can be used to remove a component delegate from a combined delegate.
Using this useful feature of delegates, you can create a list of methods that will be called when a delegate is invoked. This is known as multicasting of a delegate, also called multicast. The following program demonstrates multicasting of a delegate:
Example
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;
// Call 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
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;
// Call 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
Uses of Delegates
The following example demonstrates the use of delegates. The delegate printString
can be used to reference a method that takes a string as input and returns nothing.
We use this delegate to call two methods, the first one prints the string to the console, and the second one prints the string to a file:
Example
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 a parameter and uses it to call the methods
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