Mastering C#: Unraveling the Power of C# & OOPS

Prasoon AbhinawPrasoon Abhinaw
7 min read

Delegates in C# are powerful tools that enable callback functionality and event handling. They allow you to treat methods as objects, making it possible to pass them as arguments, return them from other methods, and store them in variables. In this article, we’ll explore the concept of C# delegates, understand when to use them, and learn how to leverage their capabilities

In another way, a Delegate is a type that represents a reference to a method with a specific signature. It acts as a contract between the calling code and the method it references, ensuring that the method has a compatible signature. In this way, a delegate is similar to an interface, but for methods. Delegates provide a way to achieve callback functionality, where a method can be executed later as a response to an event or a specific condition.

C# Delegates

Important Points About Delegates:

  • Provides a good way to encapsulate the methods.

  • Delegates are the library class in System namespace.

  • These are the type-safe pointer of any method.

  • Delegates are mainly used in implementing the call-back methods and events.

  • Delegates can be chained together as two or more methods can be called on a single event.

  • It doesn’t care about the class of the object that it references.

  • Delegates can also be used in “anonymous methods” invocation.

  • Anonymous Methods(C# 2.0) and Lambda expressions(C# 3.0) are compiled to delegate types in certain contexts. Sometimes, these features together are known as anonymous functions.

Back To Basics - Delegate in C# - Daily .NET Tips

When to use Delegates? Delegates are commonly used in the following scenarios:

  1. Event Handling: Delegates are the foundation of event-driven programming in C#. They allow objects to subscribe to and receive notifications about specific events. Events can be defined in classes, and delegates serve as the event handlers. By assigning methods to event delegates, you can define the behavior that should be executed when the event occurs.

  2. Callbacks: Callbacks involve passing a method as an argument to another method, which can be called later to perform a specific action. Delegates make it possible to implement callback mechanisms, allowing you to decouple the calling code from the specific implementation details of the callback method.

  3. Extensible and Flexible Code: Delegates enable extensible and flexible code design. By using delegates, you can define contracts that specify the expected behavior of methods. This allows other developers to provide their own implementations of those methods, making the code more modular and customizable.

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 −

Syntax: 
delegate <return type> <delegate-name> <parameter list>
Example:
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.

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. Code 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);

         //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

Types of Delegates? There are two types of delegates in C#, Singlecast delegates, and Multiplecast delegates.

Singlecast Delegate: Singlecast delegate point to a single method at a time. The delegate is assigned to a single method at a time. They are derived from System.Delegate class.

Multicast Delegate: A delegate which holds the reference of more than one method is called multi-cast delegate. A multicast delegate only contains the reference of methods which return type is void. The + and += operators are used to combine delegate instances. Multicast delegates are considered equal if they reference the same methods in the same order.

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

What are Anonymous Delegates? You can create a delegate, but there is no need to declare the method associated with it. You do not have to explicitly define a method before using the delegate. Such a method is referred to as anonymous. In other words, if a delegate contains its method definition, it is an anonymous method.

The code is an example of using an anonymous delegate.

using System;

public delegate void Test();

public class Program
{
static int Main()
{
Test Display = delegate()
{
Console.WriteLine("Anonymous Delegate method");
};

Display();
return 0;
}
}

How Delegates are Related to Events? Events and delegate work together. An event is a reference to a delegate i.e. when an event is raised, a delegate is called. In C# terms, events are a special form of delegates.

Events play an important part in user interfaces and programming notifications. Events and delegates work hand-in-hand to communicate between codes from one class to another. Events are used when something happens in one class or part of the code, and another part needs a notification.

A C# event is a class member that is activated whenever the event it was designed for occurs. It starts with a class that declares an event. Any class, including the same class that the event is declared in, may register one of its methods for the event. This occurs through a delegate, which specifies the signature of the registered method for the event. The event keyword is a delegate modifier. It must always be used in connection with a delegate.

The delegate may be one of the pre-defined .NET delegates or one you declare yourself. Whichever is appropriate, you assign the delegate to the event, which effectively registers the method that will be called when the event fires.

Program for creating a custom Singlecast delegate and event

using System;
namespace delegate_custom
{
class Program
{
public delegate void MyDelegate(int a);

public class XX
{
public event MyDelegate MyEvent;

public void RaiseEvent()
{
MyEvent(20);
Console.WriteLine("Event Raised");
}

public void Display(int x)
{
Console.WriteLine("Display Method {0}", x);
}
}

static void Main(string[] args)
{

XX obj = new XX();
obj.MyEvent += new MyDelegate(obj.Display);

obj.RaiseEvent();
Console.ReadLine();
}
}
}

Program for creating custom a Multiplecast delegate and event

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace delegate_custom_multicast
{
class Program
{
public delegate void MyDelegate(int a, int b);

public class XX
{
public event MyDelegate MyEvent;

public void RaiseEvent(int a, int b)
{
MyEvent(a, b);
Console.WriteLine("Event Raised");
}

public void Add(int x, int y)
{
Console.WriteLine("Add Method {0}", x + y);
}

public void Subtract(int x, int y)
{
Console.WriteLine("Subtract Method {0}", x - y);
}
}

static void Main(string[] args)
{
XX obj = new XX();
obj.MyEvent += new MyDelegate(obj.Add);
obj.MyEvent += new MyDelegate(obj.Subtract);
obj.RaiseEvent(20, 10);
Console.ReadLine();
}
}
}

Thanks for your time. I hope this post was helpful and gave you a mental model for Delegates and Events in C#!

0
Subscribe to my newsletter

Read articles from Prasoon Abhinaw directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Prasoon Abhinaw
Prasoon Abhinaw

I am a passionate software engineer with over 16 years of hands-on experience in the tech industry. On this blog, I aim to share my expertise, insights, and love for engineering with all of you. Whether you're a seasoned developer or just starting your journey in the world of code, this blog is here to empower you and elevate your skills. What to Expect: Expect a diverse range of content, including in-depth tutorials, coding challenges, software development tips, algorithmic insights, tech reviews, and discussions on the latest trends in the tech sphere. We'll explore various programming languages, design patterns, data structures, and best practices to help you become a more proficient engineer.