C#

C# Func

In the Microsoft Framework class library, there are some built-in delegates. Action, Predicate, and Func are some of them. I have explained Action and Predicate in my previous posts. Action and predicate delegates have restrictions. The action delegate can only take parameters and does not return anything. A predicate delegate can take parameters but return only a boolean value. To return anything other than a boolean value, a Func delegate is used.

Func is a generic delegate that encapsulates a method that can accept parameters and return some value.

Below is the declaration of Func delegates in the System namespace.

public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T arg);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
...
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);

There are 17 Func delegates defined in the class library. The first delegate cannot accept parameters and return types that are specified by the TResult parameter. Other Func delegate can take up to 16 parameters and return types that are specified by the TResult parameter. The last type is always the return type.

The in and out delegates represent covariance and contravariance. You can read more about these here.

Usage

We can only store methods in the Func delegate that have matching parameters and return types specified in the Func delegate type. For example, if we take the Func<int, int, string> delegate, then we can only store those methods that take two int parameters and return a string type.

Below is the usage of the Func delegate.

static void Main(string[] args)
{
    Func<int, int, string> func = Sum;

    string result = func(2, 4);
    Console.WriteLine(result); //Print Sum: 6
}

public static string Sum(int a, int b)
{
    string str = string.Format("Sum: {0}", (a + b));
    return str;
}

In the above example, I have declared a Func delegate with two int parameters and a return type of string. Remember, the last type is always a return type. We have declared a method called Sum, which takes two int parameters and returns a string. I have stored that Sum method in the func delegate. We call the delegate in the next line, which returns the result of type string. In the last line of the Main method, we have printed the result into the console.

Func with Anonymous functions

We can assign an anonymous function directly to the delegate. An anonymous function is an inline function that doesn’t have a function name. It is declared inline that we don’t need a separate method. We can use an anonymous function wherever a delegate is required. You can read more about the anonymous function here.

Below is the usage of the Func delegate with an anonymous function.

static void Main(string[] args)
{
    Func<int, int, string> func = delegate(int a, int b)
    {
        string str = string.Format("Sum: {0}", (a + b));
        return str;
    };

    string result = func(2, 4);
    Console.WriteLine(result); //Print Sum: 6
}

In the above example, we declared an anonymous function using delegate(…){}. We store that function directly into the func delegate instance. In this way, we don’t need to declare a separate method. We directly declared the inline function. At the end, we called delegate using two integer parameters, 2 and 4. In the last line, we print the result on the console.

Func with Lambda Expression

The lambda expression is a shorthand way of declaring anonymous functions. Below is the usage.

static void Main(string[] args)
{
    Func<int, int, string> func = (a, b) => string.Format("Sum: {0}", (a + b));

    string result = func(2, 4);
    Console.WriteLine(result); //Print Sum: 6
}