Func
The C# Func
type handles many arguments. It is a parameterized type. We specify the number and kinds of parameters, and the type of the return value.
The Func
type provides a way to store anonymous methods in a generalized and simple way. We can even use it in a data structure like an array to call a method by an index.
We use the lambda expression syntax with Func
type instances to store anonymous methods. We see type parameters: these are specified in the angle brackets.
Func
receives an int
and returns a string
. These types are within the angle brackets.bool
and an int
and returns a string
. There are 3 types within the angle brackets.Func
type instances. Each of the Invoke calls uses different parameters.using System; // Part 1: 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); // Part 2: 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); // Part 3: Func instance that has no parameters and one result value. Func<double> func3 = () => Math.PI / 2; // Part 4: call the Invoke instance method on the anonymous functions. Console.WriteLine(func1.Invoke(5)); Console.WriteLine(func2.Invoke(true, 10)); Console.WriteLine(func3.Invoke());string = 5 string = True and 10 1.5707963267949
We can call a Func
directly, without specifying the Invoke()
function. We just use the Func
like a normal method and pass it the required arguments.
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)); } }110
Func
Should you change all your C# code to use Func
invocations? This might decrease performance—using classic constructs like switch
may be faster.
Func
lookup table. It is created with 3 lambda expressions as its element values.Func
lookup table. We invoke a Func
on each iteration.switch
statement to get the same value as returned by version 1.Func
invocations.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; } } }2.82 ns Func lookup table 5.36 ns Switch
You cannot call the Invoke method with an invalid number of parameters. The Func
type stores the required parameter types and uses those to generate the Invoke method signature.
Func
type as a field, return value, local variable, or parameter in your C# programs.Func
as a field, and give it an identifier—this can make it easier to use repeatedly.The Func
parameterized type is often used with C# lambda expression syntax. It is possible to store anonymous functions inside Func
pointers and then Invoke()
them.