Generic Delegates In C#

Introduction

So here we are discussing the generic delegates. By using them, we can easily create delegates that do not depend on the data types. We can define their type at run time. Here I have explained in detail and in an easy way how to do them. Before I start with generic delegates, first of all, I want to give a quick introduction to the delegates.

Delegates

Delegates are really very useful features of C# introduced in C# 2.0. They make our projects more secure. We can implement data encapsulation with the help of delegates. Delegates are capable of holding the reference of a method, and then we can access the method without using its actual name with the help of delegates.

Why do we need Generic Delegates?

So why do we really need the Generic Delegates? Let’s have a problematic condition. If there are two methods, or if we have five methods, we can create five delegates. But when we work on such large projects, we may have to create fifty or five hundred delegates. If we want to encapsulate them by using delegates, then we have to create fifty or five hundred delegates. That will really increase the size of our code and make our application slow. Then Generic Delegates is here to help us.

Generic Delegates

By using generic delegates, we don't need to create multiple delegates in order to invoke the method. C# provides three types of delegates to deal with such conditions that may be possible in any method definition. These three types are fully capable of holding the reference of most possible method definitions, which are given below.

  1. Func Delegate
  2. Action Delegate
  3. Predicate Delegate

All three Generic Delegates are found in the System namespace, so we must add the system namespace to our program by using system; this namespace is by default added to the program automatically.

Func Delegate

The func generic delegate is defined in the system namespace. This delegate takes a 1-16 input parameter and must have one return parameter, otherwise it will raise an error like CS7003 There is an unexpected use of an unbound generic name, so it is a must to have a return parameter if you are using Func Generic Delegate. The last parameter is treated as a return type.
 
Syntax to create Func Delegate

Func<parameter list,output value> Object_name= new Func <parameter list,output value>(method_name);

Let's have an example

suppose we have a method

public static double Addition_Func(int no1, float no2, double no3) {
    return no1 + no2 + no3;
}

Here method name  is Additon_Func that returns a double value and has three input parameters, to call this method we have to define a delegate like this

Func<int, float, double, double> Func_Object = new Func<int, float, double, double>(Addition_Func);

Here the last parameter is double, which is the return type of the passed method Addition_Func. When we call the method with the object this will invoke the Addition_Func.

Invoking the method by using  Func Generic delegate.

There are two ways available in C# to invoke method

  1. Object_Name(parameters);
  2. Object_Name.Invoke(parameters);

Let's have a quick introduction to Invoke Keyword 

Invoke

This will invoke the specified method that is assigned to the Delegate object. This will search for the method in their parent class until it is not found. This will schedule the method to the thread once it receives the method definition.

Note
it is not mandatory to use Invoke to invoke the method.

Invoking without Invoke

double Result = Func_Object(100, 125.45f, 456.789);

Here we call the method Addition_Func that is previously passed to Func_object. Here we created a double type variable Result that holds the return value that is produced by Addition_Func.

Invoking with Invoke

double Result = Func_Object.Invoke(100, 125.45f, 456.789);

Here almost things are the same except Invoke  keyword 

Both invocations produce the same output after the execution

Action Delegate

The Action Delegate is needed when we need to invoke a method that doesn't have any return type. Action Delegate is capable of taking a maximum of 16 parameters as arguments, which means it has 16 overload methods.

Syntax to create Action Delegate

Action<parameter list,output value> Object_name= new Action <parameter list,output value>(method_name);

Let's have an example

suppose we have a method

public static void Addition_Action(int no1, float no2, double no3) {
    Console.WriteLine(no1 + no2 + no3);
}

Here method name  is Addition_Action which does not return any type of value but has three input parameters to call this method, we have to define a delegate like this

Action<int, float, double> Action_Object = new Action<int, float, double>(Addition_Action);

Here we created an object of Action class that is Action_object. Here we passed the same parameters as presented in the Addition_Action method definition 

to invoke this method we use

 Action_Object.Invoke(50, 255.45f, 123.456);

object  name .invoke and passing the required parameters 

Predicate Generic Delegate

The Predicate Generic Delegate is useful in such conditions where we need to pass a String to a method. In Predicate Generic Delegate there is only one argument that can be passed. By default Predicate Generic Delegate returns a Boolean value that may be true or false

Syntax to create Predicate Generic Delegate

Predicate<String> Object_name= new Predicate<String>(method_name);

Let's have an example

suppose we have a method

public static bool Validate_string(string name) {
    if (name.Length < 15) return true;
    return false;
}

Here method name is Validate_string that returns a boolean value and has one input parameter of string type to call this method we have to define a Predicate delegate like this

Predicate<string> Predicate_Object = new Predicate<string>(Validate_string);

to invoke this method we use

bool Status = Predicate_Object.Invoke("shivam payasi");

Here we created a bool type variable Status that holds the value returned by method Validate_string

Let's have a look at all examples 

using System;
namespace Generic_DeleGates {
    public class GenericDelegates {
        static void Main(string[] args) {
            Func < int, float, double, double > Func_Object = new Func < int, float, double, double > (Addition_Func);
            double Result = Func_Object.Invoke(100, 125.45 f, 456.789);
            Console.WriteLine("Result of Addition with Func Generic Delegate: " + Result);
            Action < int, float, double > Action_Object = new Action < int, float, double > (Addition_Action);
            Action_Object.Invoke(50, 255.45 f, 123.456);
            Predicate < string > Predicate_Object = new Predicate < string > (Validate_string);
            bool Status = Predicate_Object.Invoke("shivam payasi");
            Console.WriteLine("Resultwith Predicate Generic Delegate: " + Status);
            Console.ReadLine();
        }
        public static double Addition_Func(int no1, float no2, double no3) {
            return no1 + no2 + no3;
        }
        public static void Addition_Action(int no1, float no2, double no3) {
            Console.WriteLine("Result of Addition with Action Generic Delegate: " + (no1 + no2 + no3));
        }
        public static bool Validate_string(string name) {
            if (name.Length < 15) return true;
            return false;
        }
    }
}

Here is the output

Summary

Here we started with a quick introduction of Delegates and then discussed Generic Delegates and their types.

All three types of generic delegate are useful in their appropriate conditions. One thing to remember is that the Func Generic Delegate is very useful when we need to call functions that have one return value and multiple input values or no input parameters. Action Generic Delegate is useful when we need to call a function that doesn't have any return value but has a single or multiple input values. The Predicate Generic Delegate is useful when we need to call a function that returns a boolean value and has a string parameter as input.