Using Delegates in (C#)
What are Delegates in C#?
The delegates in C# are the Function Pointer. It means they hold the reference of a method or
function and then call that method for execution.
How to Create a Delegates in C#?
A delegate can be defined by using the delegate keyword. Behind the scene, when the compiler sees
the delegate keyword, it actually generates a class that inherits from some other .NET Framework
delegate classes.
The syntax to create a delegate in C# is very much like the abstract method declaration. In abstract
method declaration, we use the abstract keyword whereas, in delegate, we need to use the delegate
keyword. The syntax for defining a delegate in C# is as follows:
<Access Modifier> delegate <Return Type> <Delegate Name> (Parameter List);
Public delegate void voidDelegate();
The following is an example of a delegate. This particular delegate you can think of is a one-way
pipeline. It’s void, nothing is going to return back. Data only goes forward. The name of the delegate
is WorkPerformedHandler and it takes two parameters. The first parameter is integer hours and the
second parameter is worktype which is going to be an Enumeration. Now, if you remove the delegate
keyword, then it looks like a method.
public delegate void WorkPerformedHandler(int hours, WorkType workType);
A delegate is a blueprint for the method, which is going to dump the data into the event handler. The
delegate is kind of a pipeline. And what we want then, is a way to dump some data from Point A to
Point B.
Now, we have our data somewhere in our program and we want to route those data over to this
Handler method. How we can route the data into the Handler Method? We are going to route the
data which is stored somewhere in our program over to this Handler Method using the pipeline i.e.
using a delegate. In delegate, we need to define the parameters which will route the data from
point A to point B (i.e. Handler method).
In this case, the pipeline only accepts two parameters and it must be of type int and WorkType
otherwise it will not compile. So, now we have one way to delegate the data from point A to Point B.
So, the delegate knows how to pass data.
The delegate signature and handler method signature must be matched. As we have defined the
delegate with two parameters of int and WorkType type. Now, if the handler method wants to receive
the data from the pipeline, then the handler must have the same number, type, and order of
parameters as the delegate.
Parameters type, order, and number must be the same, otherwise, the Handler Method will not
receive the data from the delegate. The parameter names do not matter. You can see that we have
given the parameter name of the delegate as hours and workType and we have provided different
names to the handler Method and that is fine.
How to use the Delegate in C#?
For this, we need to create an instance of the delegate. And while creating the instance we need to
specify the Handler Method name where we want to dump the data. If the Handler Method is a static
method, you can access that method directly or using the class name and if the Handler Method is a
non-static method, then you need to access the Handler Method using the object name.
When we declare a delegate, it will create a class inheriting from the MulticastDelegate and as this
is a class, we can create an instance of the delegate by using the new keyword. And notice to the
constructor, that we are passing the Delegate handler Method name. In our example, as the
Handler Method is a static method and as both method and the instance that we are creating are
present in the same class, we can pass the method name without using the class name, But if the
method is non-static, then you need to create an instance of the class to which the method belongs,
and using that instance, you need to call the method inside the delegate constructor.
How to Invoke a delegate in C#?
Invoking a delegate is very simple. The way we call a method, in the same way, we can call a delegate,
and the values for the parameters we need to pass within the parenthesis are as follows. Here, we
are passing 5 as the work hours and WorkType as Golf.
del1(10, WorkType.Golf);
And the above statement will invoke the handler method Manager_WorkPerformed dynamically at
runtime.
Once we create an instance of a delegate, then we need to call the delegate by providing the required
values to the parameters so that the methods get executed internally which is bound with the
delegates. We can also use Invoke method to execute the delegates. For example:
del1.Invoke(10, WorkType.Golf);
How to Invoke Methods using Delegates in C#?
If you want to invoke or call a method using delegates, then you need to follow the following three
steps.
1. Declare a Delegate
2. Instantiating a Delegate
3. Invoking a Delegate
Another Example to Understand Delegates in C#:
1. **Define the delegate type**:
public delegate void MyDelegate(string message);
2. **Create methods that match the delegate signature**:
public class MyClass
{
public void ShowMessage(string message)
{
Console.WriteLine("Message: " + message);
}
public void ShowUpperCaseMessage(string message)
{
Console.WriteLine("Upper Case Message: " + message.ToUpper());
}
}
3. **Instantiate the delegate and invoke it**:
public class Program
{
public static void Main()
{
MyClass myClass = new MyClass();
// Create a delegate instance pointing to the ShowMessage method
MyDelegate myDelegate = new MyDelegate(myClass.ShowMessage);
// Invoke the delegate
myDelegate("Hello, World!");
// Change the delegate to point to the ShowUpperCaseMessage method
myDelegate = new MyDelegate(myClass.ShowUpperCaseMessage);
// Invoke the delegate again
myDelegate("Hello, World!");
}
}
In this example:
- We define a delegate type `MyDelegate` that takes a single `string` parameter and returns `void`.
- We create two methods (`ShowMessage` and `ShowUpperCaseMessage`) in the `MyClass` class that
match the delegate's signature.
- In the `Main` method of the `Program` class, we instantiate `MyClass` and create a delegate instance
`myDelegate` pointing to the `ShowMessage` method.
- We invoke the delegate, which calls `ShowMessage` and prints the message.
- We then change the delegate to point to the `ShowUpperCaseMessage` method and invoke it again,
which calls `ShowUpperCaseMessage` and prints the message in upper case.
The output will be:
Message: Hello, World!
Upper Case Message: HELLO, WORLD!
Rules of using Delegates in C#:
1. A delegate in C# is a user-defined type and hence before invoking a method using a
delegate, we must have to define that delegate first.
2. The signature of the delegate must match the signature of the method, the delegate points
to otherwise we will get a compiler error. This is the reason why delegates are called type-
safe function pointers.
What are the Types of Delegates in C#?
The Delegates in C# are classified into two types as
1. Single Cast Delegate
2. Multicast Delegate
If a delegate is used for invoking a single method, then it is called a single cast delegate or unicast
delegate. In other words, we can say that the delegates that represent only a single function are
known as single cast delegates.
If a delegate is used for invoking multiple methods, then it is known as the multicast delegate. Or the
delegates that represent more than one function are called Multicast delegates.
What is Multicast Delegate in C#?
A Multicast Delegate in C# is a delegate that holds the references of more than one handler function.
When we invoke the multicast delegate, then all the functions which are referenced by the delegate
are going to be invoked. If you want to call multiple methods using a delegate then all the method
signatures should be the same.
So, a multicast delegate is just an array of multiple pipelines or multiple delegates. The delegates
are going to be invoked in the same order as they are placed in the invocation list. An InvocationList
is nothing but an array of delegates or pipelines where each pipeline will dump data into a different
method. If this is not clear at the moment don’t worry, we will try to understand this with multiple
examples
Multicast Delegate Example in C#:
Define the delegate type:
public delegate void MyDelegate(string message);
Create methods that match the delegate signature:
public class MyClass
{
public void Method1(string message)
{
Console.WriteLine("Method1: " + message);
}
public void Method2(string message)
{
Console.WriteLine("Method2: " + message);
}
public void Method3(string message)
{
Console.WriteLine("Method3: " + message);
}
}
Instantiate the delegate and add methods to it:
public class Program
{
public static void Main()
{ MyClass myClass = new MyClass();
// Create a delegate instance
MyDelegate myDelegate = new
MyDelegate(myClass.Method1);
// Add additional methods to the delegate
myDelegate += myClass.Method2;
myDelegate += myClass.Method3;
// Invoke the delegate
In this example:
myDelegate("Hello, World!");
}
}
We define a delegate type MyDelegate that takes a single string parameter and returns void.
We create three methods (Method1, Method2, and Method3) in the MyClass class that match the
delegate's signature.
In the Main method of the Program class, we instantiate MyClass and create a delegate instance
myDelegate pointing to Method1.
We then add Method2 and Method3 to the delegate using the += operator.
When we invoke myDelegate with the string "Hello, World!", it calls all three methods in the order
they were added.
The output will be:
Method1: Hello, World!
Method2: Hello, World!
Method3: Hello, World!
Multicast Delegates with Return Type in C#:
A multicast delegate invokes the methods in the same order in which they are added to the
Invocation List .As of now, the examples we have discussed using Multicast delegate, are not
returning anything i.e. the return type is void. Now, what happens if the delegate has a return type?
If the delegate has a return type other than void, and if the delegate is a multicast delegate, then
only the value of the last invoked method will be returned. Along the same lines, if the delegate has
an out parameter, the value of the output parameter will be the value assigned by the last invoked
method from the Invocation List.
1. **Define the delegate type**:
public delegate int MyDelegate(int x, int y);
2. **Create methods that match the delegate signature**:
public class MyClass
{
public int Add(int x, int y)
{
int result = x + y;
Console.WriteLine("Add: " + result);
return result;
}
public int Subtract(int x, int y)
{
int result = x - y;
Console.WriteLine("Subtract: " + result);
return result;
}
public int Multiply(int x, int y)
{
int result = x * y;
Console.WriteLine("Multiply: " + result);
return result;
}
}
3. **Instantiate the delegate and add methods to it**:
public class Program
{
public static void Main()
{
MyClass myClass = new MyClass();
// Create a delegate instance
MyDelegate myDelegate = new MyDelegate(myClass.Add);
// Add additional methods to the delegate
myDelegate += myClass.Subtract;
myDelegate += myClass.Multiply;
// Invoke the delegate
int result = myDelegate(10, 5);
Console.WriteLine("Result of last method invoked: " + result);
}
}
In this example:
- We define a delegate type `MyDelegate` that takes two `int` parameters and returns an `int`.
- We create three methods (`Add`, `Subtract`, and `Multiply`) in the `MyClass` class that match the
delegate's signature.
- In the `Main` method of the `Program` class, we instantiate `MyClass` and create a delegate
instance `myDelegate` pointing to `Add`.
- We then add `Subtract` and `Multiply` to the delegate using the `+=` operator.
- When we invoke `myDelegate` with the arguments `10` and `5`, it calls all three methods in the
order they were added. However, only the result of the last method (`Multiply`) is returned and
stored in the `result` variable.
The output will be:
Add: 15
Subtract: 5
Multiply: 50
Result of last method invoked: 50