Generic Delegates in C# With Examples

In the previous article, we have learned about the delegates and their types. Now in this article, we are going to discuss the generic delegates in C#.

What are the generic delegates?

The  Func ,  Action  and  Predicate  are the three generic delegates which were introduced in .NET 3.5 and are availables in System namespace.

We can make use of all these three predefined generic delegates when we want to invoke the methods without defining the delegates explicitly.

Func delegate in C#

Func generic delegates in c#

Func is a generic delegate that is available in the System namespace.

It can take up to 16 input parameters of the same or different data types and one out parameter.

The last parameter in the Func delegate is always considered as an out parameter to return the value.
The input parameters are optional but the out parameter is mandatory to pass in the Func delegate.

Func delegate can be also used with the anonymous method and the lambda expression.

We can use  Func  delegate to point those methods which can take zero, one or more input parameters, and return some value.

Note: Func delegate doesn’t allow to pass ref and out parameters.

Syntax of Func delegate

// Signature to define Func delegate.

public delegate TResult Func<in T, out TResult>(T arg);

// Func delegate can take up to 16 input parameters and one out parameter.

public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);



//The last parameter is an out parameter

Example to define a delegate in C#

Before moving forward, let’s first create an example of a simple single cast delegate, and later on, we will achieve the same thing using the Func delegate.

To create a normal delegate we have to follow these four steps.

    • Declare a delegate type
    • Create methods having the same signature as delegate type
    • Create an instance of the delegate type
    • Invoke the delegate object

In the following example, we are defining a delegate separately.

using System;
namespace DelegateDemo
{
    class Program
    {
        // Declaring a delegate
        
        public delegate double MyDelegate(int num1, float num2);

        static void Main(string[] args)
        {

         // Instantiating the delegate
        // and passing the method as parameter

        MyDelegate myDelegate = new MyDelegate(AddNumbers);

        // Invoking a delegate

        double output = myDelegate.Invoke(10, 20.5f);
        Console.WriteLine($"Output : {output}");

        }
        // Create method having same signature as delegate
        public static double AddNumbers(int num1, float num2)
        {
            return num1 + num2;
        }
    }

    // Output : 30.5
}

In the above program, we have defined a delegate explicitly to point a method called “AddNumbers”.
This method takes two input parameters of int and float type and returns a double value.
Once we run the program we will get the result as expected.

To define the delegate like above is fine, except when we need to define so many delegates explicitly to point multiple methods having different signatures.
So defining like the above delegate to point matching method signature can be eliminated by using the generic delegates in C#.

To eliminates defining the delegate separately we can use the generic delegates. Let’s create the above program using a  Func  generic delegate.

Example of Func delegate

using System;
namespace FuncDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {

            Func<int, float, double> funcDelegate = AddNumbers;

            double output = funcDelegate.Invoke(10, 20.5f);

            Console.WriteLine($"Output : {output}");

        }     
        public static double AddNumbers(int num1, float num2)
        {
            return num1 + num2;
        }
    }

    // Output : 30.5
}

The following is the output of the above program.

Func delegate output

Example of Func delegate with an anonymous method

In the following example, we are assigning an anonymous method to the Func delegate by using the delegate keyword.

If we are using an anonymous method, we don’t need to declare a separate named method.

You can read more about the anonymous method here.

using System;
namespace FuncDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {

            Func<int, float, double> funcDelegate = delegate (int num1, float num2)
            {
                return num1 + num2;
            };

            double output = funcDelegate.Invoke(10, 20.5f);

            Console.WriteLine($"Output : {output}");

        }           
    }

    // Output : 30.5
}

In the above example, an anonymous method is directly assigned to the Func delegate which takes two input parameters. An anonymous method is useful when we want to write an inline statement without creating a separate named method.

Func generic delegate with anonymous method

Example of Func delegate with the lambda expression

In the following example, we are using Func delegate with the lambda expression. Lambda expression is basically shorthand or an enhancement for declaring an anonymous method in C#.

using System;
namespace FuncDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {

         Func<int, float, double> funcDelegate = (int num1, float num2) => (num1 + num2);
           
         double output = funcDelegate.Invoke(10, 20.5f);

         Console.WriteLine($"Output : {output}");

        }           
    }

    // Output : 30.5
}

Action delegate in C#

The  Action  delegate is very similar to the  Func  delegate. It can also accept up to 16 input parameters but it doesn’t return any value.

Action delegate is a generic delegate in which return type is always void. We can use action delegate to point those methods which return void and accept zero or more input parameters.

Action delegates are of two types:

Action: Encapsulates a method that has no parameters and does not return a value.

Action<in T1,…,inT16>: Encapsulates a method that has zero or more input parameters of same or different data types and does not return a value.

Syntax of Action delegate

// Encapsulates a method that has a single parameter and does not return a value.
public delegate void Action<in T>(T obj);

// Encapsulates a method that can accept up to 16 input parameter and
// does not return a value.

public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);

// The Action generic delegate can accept zero to 16 input parameters.

Example of non-generic Action delegate

The non-generic delegate takes the reference of a method that returns void and has no parameter.

using System;
namespace ActionDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {
            // Non generic action delegate
            Action action = PrintName;
            action.Invoke();

        }     
        public static void PrintName()
        {
           Console.WriteLine("Shekh Ali");
        }
    }

    // Output : Shekh Ali
}

Example of Action generic delegate

In the below example, we are using Action delegate to hold the reference of a method that is accepting two input parameters of integer type and returns void.

using System;
namespace ActionDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {
            // Generic Action delegate
            Action<int,int> action = AddTwoNumbers;
            action.Invoke(30,20);

        }

        public static void AddTwoNumbers(int num1, int num2)
        {
           Console.WriteLine(num1 + num2);
        }

    }

    // Output : 50
}

Action generic delegate with an anonymous method

using System;
namespace ActionDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {
            // Generic Action delegate with anonymous method

            Action<int, int> action = delegate (int num1, int num2)
             {
                 Console.WriteLine(num1 + num2);
             };

            action.Invoke(30, 20);
        }
    }

    // Output : 50
}

Action generic delegate with the lambda expression

In the below example we are using Action delegate with the lambda expression.

using System;
namespace ActionDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {
            // Generic Action delegate with lambda expression

            Action<int, int> action = (num1, num2) =>
            {
                Console.WriteLine(num1 + num2);
            };
             

            action.Invoke(30, 20);
        }
    }

    // Output : 50
}

Predicate generic delegate in C#

The  Predicate  is a generic delegate which is available in System namespace.
It takes one input parameter and returns a  boolean  value.

A predicate delegate is generally used to check whether a parameter meets a specific condition or not.
If it meets the criteria it will return  true  otherwise  false  .

The Predicate delegate is mostly used in a lambda expression to filter the results.

Syntax of predicate delegate

Following is the syntax to declare predicate generic delegate in C#.

public delegate bool Predicate<in T>(T obj);

Example of Predicate delegate

In the following example, we are checking whether the entered number is even or not. If the entered number is even it will return true otherwise false.

using System;
namespace PredicateDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {

         // Predicate delegate

         Predicate<int> predicate = IsEvenNumber;

         bool result =   predicate.Invoke(10);

         Console.WriteLine(result);

        }

        public static bool IsEvenNumber(int number)
        {
           if (number % 2 == 0)
               return true;
           else
              return  false;
        }
    }

    // Output : True
}

Predicate delegate with an anonymous method

using System;
namespace PredicateDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {

            // Predicate delegate with anonymous method

            Predicate<int> predicate = delegate(int number)
            {
                if (number % 2 == 0)
                    return true;
                else
                    return false;
            };

         bool result =   predicate.Invoke(10);

         Console.WriteLine(result);

        }
       
    }

    // Output : True
}

Predicate delegate with the lambda Expression

using System;
namespace PredicateDelegateDemo
{
    class Program
    {     
        static void Main(string[] args)
        {

            // Predicate delegate with lambda expression

            Predicate<int> predicate = (number)=>
            {
                if (number % 2 == 0)
                    return true;
                else
                    return false;
            };

         bool result =   predicate.Invoke(10);

         Console.WriteLine(result);

        }
      
    }

    // Output : True
}

Conclusion:

Today we learned all about the generic delegates available in C# such as Func, Action, and Predicate delegates with multiple examples.
I hope you enjoyed this post and found it useful.

Thanks for visiting.

Leave a Reply

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

three + 17 =