Generic Delegates in C# With Examples: Func, Action, and Predicate delegates

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

Generic Delegates in C#
Generic Delegates in C#

What are the generic delegates in C#?

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

They are like ready-made templates for functions that you can use in your code. Here’s why and how you should use them:

Func

The Func delegate represents a method that can take input parameters from 0 to 16 and return a single value. You should use it when you want to define a method that always returns a value, like a mathematical calculation.

For example:

 using System;
public class GenericDelegateExample
{
    
    public static void Main(string[] args)
    {
       Func<int, int, int> add = (a, b) => a + b;
       int result = add(5, 3); 
       Console.WriteLine($"Output : {result}"); // Result will be 8
    }
}

Action

The Action delegate is similar to Func, but it doesn’t return a value (void). It can also take from 0 to 16 input parameters. This delegate is used for methods that perform an action but don’t return a result, like logging or printing to the console.

For example:

using System;

public class GenericDelegateExample
{
    
    public static void Main(string[] args)
    { // Action Delegate Example
       Action<string> greet = (name) => Console.WriteLine($"Hello, {name}!");
          greet("Radha");  // Prints "Hello, Radha!"

    }
}

Predicate

The Predicate delegate represents a method that takes a single parameter and returns a Boolean value. So, If you need a delegate to check a condition and return a Boolean result, go for Predicate.

It takes only one input parameter and returns true or false. 

Predicate delegate is great for scenarios where you need to check conditions, like filtering a list based on a specific criterion.

For Example:

// Example: 1
Predicate<int> isEven = (num) => num % 2 == 0;
bool even = isEven(6); // 'even' will be 'true'

// Example: 2
Predicate<string> isLong = s => s.Length > 5;
bool result = isLong("example"); // result is true

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

Let’s understand these generic delegates in more details.

Func delegate in C#

Func generic delegates in c#
Func generic delegates in c#

The 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 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 also be 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 passing 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 the 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 to 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.

Defining the delegate like above is fine, except when we need to define so many delegates explicitly to point to 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 the return type is always void. We can use action delegate to point to 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 the 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 generic predicate 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.

FAQs:

Q: Delegate in C#: What does it mean?

A delegate is a reference type data type that refers to any method with the same signature as the delegate.

Delegates are commonly used for event handling, callback mechanisms, and dynamic method invocation. They provide flexibility and decouple the caller from the actual method implementation.

Q: What are the different types of delegates in C#?

There are three types of delegates available in C#:
1. Single Delegate
2. Multicast Delegate
3. Generic Delegate (Func, Action, and Predicate delegate)

Q: Why is delegate used in C#?

In C#, Delegates are mainly used to define callback methods and implement event handling and are declared using the “delegate” keyword.

Q: What is the difference between event and delegate in C#?

A delegate is a function pointer. It holds the reference of one or more methods with the same signature at runtime. The delegate is independent and doesn’t rely on events. On the other hand, An event is dependent on a delegate and cannot be created without delegates.

Q: Why should I use generic delegates?

Using generic delegates simplifies code by providing a standardized way to work with methods.
Instead of defining custom delegate types for each method signature, you can use Action delegate for methods that don’t return a value, Func delegate for methods that return a value, and Predicate delegate for methods that return a Boolean value.

Recommended Articles:

I truly hope you enjoyed and learned from this article “Generic Delegates in C#”. Please leave any feedback, comments, or questions in the comment section below.

Shekh Ali
5 1 vote
Article Rating
Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments