Understand C# Delegates basics with its practical application

Delegates can be tricky to understand for many new developers even after going through the books and posts, but I am sure this post is going to help you understand and with little more effort master this concept.

(Please post all your queries in the comments below and I will try to reply to most if not all of them. )

Let’s start with the definition first:

A delegate is a type that represents references to methods with a specific signature. It acts as a function pointer or a contract between a publisher and a subscriber.

Do not rush through the definition. Reread it. Here it is important to understand that delegate is a type like other types in C# like class, structure, interface, and enumeration.

Let’s digress a bit and focus on what is the type and then we will come back to the Delegate Type.

C# is a strongly typed language which means that variables, expressions, and function parameters must adhere to their declared data types, and the compiler checks for type compatibility before allowing code to be executed. If there is a type mismatch, the compiler generates an error. You already know that Type can be of two types : Reference or Value type and based on the type it is decided whether it will be stored i.e. (on stack or heap).

e.g. int can store integer value only and also the maximum value it can store depends upon whether it is int32 or int64, similarly string can store string value. If you assign the string to int it will throw an error at the compile time only thus helping to avoid the error at the run time. The point I am trying to make here is that each type in C# sets some rules which has to be adhered. Let’s cut to the chase and come back to Delegate.

A delegate is also a Type, pointing to a method that adheres to the signature defined in that delegate. Let’s compare delegate with class and then you will be able to understand and remember it easily.

To declare a class, you use the access modifier (public|private|internal|protected) class keyword followed by the class name. 

Similarly, to declare a delegate, you use the delegate keyword, specifying the return type and delegate name, along with any parameters if needed. For example


You might be thinking that delegate declaration looks like how we define a method,if you are thinking like that then you are on the right track. The reason it looks like a method is because delegate is used to point to a method or method that adheres to the Delegates signature.

Let’s dig little deep and  first understand how can a delegate be created.

      1. Delegate Declaration:To define a delegate, you specify the delegate’s signature, which includes the return type and parameters of the method it can reference. The syntax for declaring a delegate is as follows:

    delegate <return_type> <delegate_name>(<parameters>);

    For example, let’s define a delegate named MathOperationDelegate that represents a method that takes two integers as parameters and returns an integer:

    If you are wondering why delegates follows certain signature then let me explain that to you – as you know delegates are function pointer i.e. it can point to certain function. To ensure type safety , delegates doesn’t simply point to any function but only those function which matches it’s signature. i.e the method it can point should match the return type and parameters that are included in the delegates declaration.

    I think it is right time to touch upon Action, Func and Predicate as well. Now a days , generics are so common that .Net library has created some generic Delegates for us which we can use instead of creating our own Delegates. And with Generic delegates, they ensure that any function you want to point can be pointed using their inbuilt delegates – Action, Func and Predicate.

    Action, Func, Predicate ( These are generic delegates in .Net Library) . Action points to method/function which doesn’t have return type (void return type). Func delegate can point to method/function which has some return type. Predicate is special Func delegate which can point to method/function which returns bool.

    So how does one Action or Func can be used to point to method which I have created which can have its own return type . For example I have a method which takes two parameter (int and string) and return void use Action<int,string>. If I have a method which takes one parameter (int) and return one (string) then you can use Function<int,string>

    In Func, the last type is always used for the return type.

     Refer to the IDE screenshot above which makes it clear. 

    This is how Action delegates look in Visual Studio IDE.

    You can write the same code using Func like this.

       Func<int,int,int> myFunc

        1. Creating Delegate Instances:

      Once you have defined a delegate, you can create instances of it by assigning methods that match the delegate’s signature. You can assign a single method or multiple methods to a delegate instance using the += operator.

      Using Func you can rewrite the same code as below.

          1. Invoking Delegates

        Invoking Delegates: To invoke a delegate and execute the method(s) it references, you simply call the delegate as if it were a method. The delegate will, in turn, call the assigned method(s).

        In this example, we invoke the delegate instances addDelegate and subtractDelegate by passing the required arguments. The delegate calls the respective methods (Add and Subtract) and returns the results.

        Delegates can be multicast : meaning they can reference multiple methods. This allows you to combine multiple methods into a single delegate instance. The += and -= operators are used to add and remove methods from a multicast delegate, respectively.

        Application of Delegates– At times, we want any particular method to call our method (callback scenario) when certain condition is met or once it has completed it’s execution , or we want to pass a logic which we have written in our method (like in LINQ methods scenarios, more on that below) in such cases delegates can be very useful . You need to take Delegate as the argument in such case which will allow you to pass the function directly.

        Delegate allows you to treat methods as first-class entities, meaning you can pass them as arguments to other methods, store them in variables, and invoke them dynamically.

        Delegates in C# provide a powerful mechanism for implementing callback functionality and enabling event-based programming. They offer flexibility and abstraction by decoupling the method being called from the code that invokes it. Delegates are extensively used in various areas, including event handling, LINQ queries, asynchronous programming with async and await, and more.

        Please write in comment section if you find this useful or if you have any suggestions.

        Leave a Reply

        Your email address will not be published. Required fields are marked *