C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
So: The first type parameters are the arguments to the methods, and the final type parameter is the return value.
Generic Class, MethodReturnFunc 1: The first Func receives an int and returns a string and it is declared as Func<int, string>.
Func 2: The second receives a bool and an int and returns a string. It is declared with Func<bool, int, string>.
Func 3: The third returns a value. This is based on the value of PI (just to make things interesting).
Int, uintStringsBoolFinally: This program calls the Invoke method on the Func type instances. Each of the Invoke calls uses different parameters.
C# program that uses Func generic type and lambdas
using System;
class Program
{
    static void Main()
    {
        //
        // Create a Func that has 1 parameter and 1 return value.
        // ... Parameter is an integer, result value is a string.
        //
        Func<int, string> func1 = (x) =>
            string.Format("string = {0}", x);
        //
        // Func instance with two parameters and one result.
        // ... Receives bool and int, returns string.
        //
        Func<bool, int, string> func2 = (b, x) =>
            string.Format("string = {0} and {1}", b, x);
        //
        // Func instance that has no parameters and one result value.
        //
        Func<double> func3 = () => Math.PI / 2;
        //
        // Call the Invoke instance method on the anonymous functions.
        //
        Console.WriteLine(func1.Invoke(5));
        Console.WriteLine(func2.Invoke(true, 10));
        Console.WriteLine(func3.Invoke());
    }
}
Output
string = 5
string = True and 10
1.5707963267949
C# program that calls Func directly
using System;
class Program
{
    static void Main()
    {
        Func<int, int> addOneHundred = a => a + 100;
        // We can call the Func directly without Invoke.
        Console.WriteLine(addOneHundred(10));
    }
}
Output
110
Here: We create a 3-Func lookup table. It is created with 3 lambda expressions as its element values.
Version 1: In this version of the code, we test the Func lookup table. We invoke a Func on each iteration.
Version 2: In this code, we use a switch statement to get the same value as returned by version 1.
SwitchResult: We lose some performance with the Func invocations. Using a switch is faster (and probably simpler to understand).
C# program that tests Func performance
using System;
using System.Diagnostics;
class Program
{
    const int _max = 10000000;
    static void Main()
    {
        // A Func lookup table.
        var lookup = new Func<int, int>[]
        {
            a => a + 10,
            a => a + 20,
            a => a + 30
        };
        // Version 1: use Func table.
        var s1 = Stopwatch.StartNew();
        for (int i = 0; i < _max; i++)
        {
            if (Version1(lookup, i) == -1)
            {
                return;
            }
        }
        s1.Stop();
        // Version 2: use switch.
        var s2 = Stopwatch.StartNew();
        for (int i = 0; i < _max; i++)
        {
            if (Version2(i) == -1)
            {
                return;
            }
        }
        s2.Stop();
        Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
            _max).ToString("0.00 ns"));
        Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
            _max).ToString("0.00 ns"));
    }
    static int Version1(Func<int, int>[] lookup, int i)
    {
        // Use lookup table.
        return lookup[i % 3](i);
    }
    static int Version2(int i)
    {
        // Use switch.
        switch (i % 3)
        {
            default:
            case 0:
                return i + 10;
            case 1:
                return i + 20;
            case 2:
                return i + 30;
        }
    }
}
Output
4.64 ns    Func lookup table
3.58 ns    Switch
And: You can use the Func type as a field, return value, local variable, or parameter in your C# programs.
Important: You must specify the full type name with the type parameters. In this way we can store delegates by their signatures.
Example: You can add the Func<int, string> as a field, and give it an identifier.