Introduction
A delegate is a C# type similar to function pointers in C++. It encapsulates references to one or multiple methods. Func<> is a special kind of Multicast Delegate used frequently with LINQ and Enumerable extensions. Let's have a close look at Func<> delegates.
Func Delegates
Func delegates are pointers to methods that take one or more parameters and must return a value. There are many overloaded Func delegates. Please see the documentation for a better understanding of those. In this article let's have a general idea of how to use it programmatically.
Usage
Generelly it's used with anonymous methods as follows:
- Func<int, int, int, long> add = delegate(int a, int b, int c) { return a + b + c; };
- Console.WriteLine(add(2, 3, 4));
The similar kind can be replaced by a lambda expression that is more readable and easy to write and understand.
- Func<int, int, int, long> add = (a, b, c) => a + b + c;
- Console.WriteLine(add(2, 3, 4));
But the difference is that the return type is inferred by the compiler this time.
You don't use the Func<> as in the preceding examples generally. The most usefulness of Func<> is when you want to build an extension method and use it globally. Most of the LINQ extensions take Func as a parameter. Here is a simple use:
- public static bool EnumerableContains<S, T>(this IEnumerable<S> obj,
- Func<S, T> comparer, T valueToMatch)
- {
- return obj.Any(l => comparer(l).Equals(valueToMatch));
- }
You can call this on an IEnumerable object as:
- var obj = new List<Person> { new Person { ID = 1, Name = "Arunava" }, new Person { ID = 2, Name = "Bubu" } };
- bool res=obj.EnumerableContains(data => data.Name, "Bubu");
- Console.WriteLine(res);
Func delegates also support co-variance and contra-variance. It means you can pass a parent class and can return a subclass object and vice-versa.
The casting happens internally by the compiler, so you don't need to worry about it. Let's see a simple example:
- static string PrintHellow() { return "Hellow!"; }
- static void Main()
- {
- Func<object> delegateObj = PrintHellow;
- }
Here, the method's return type is a string that is lower in the class hierarchy than an object. But this code is supported in C# 5.0 and produces the expected result. You don't need to typecast it internally. This is a great support provided by C# delegate.
The Func as Predicate
Previously we have an object in C# called a Predicate. It is still supported but generally the modern C# programmers understand Predicate as a special kind of Func delegate. This kind of func delegate returns a bool. This is mostly used in expressions and LINQ. Let's see the example of a StartsWith extension. It expects a predicate as a parameter as in the following:
- var obj = new List<Person> { new Person { ID = 1, Name = "Arunava" }, new Person { ID = 2, Name = "Bubu" } };
- var result = obj.Where(data => data.Name.StartsWith("b",StringComparison.CurrentCultureIgnoreCase));
I hope this helps.