If you use method syntax, you'll see func quite often, for instance in Where
, GroupBy
, Join
, etc
Every method with some input parameters and one return value can be translated to a Func<...>
as follows
MyReturnType DoSomething(ParameterType1 p1, ParameterType2, p2) {...}
Func<ParameterType1, ParameterType2, MyReturnType> myFunc = (x, y) => DoSomething(x, y);
The part Func<ParameterType1, ParameterType2, MyReturnType>
means: a function with two input parameters and one return value. The input parameters are of type ParameterType1
and ParameterType2
, in this order. The return value is of MyReturnType
.
You instantiate an object of Func<ParameterType1, ParameterType2, MyReturnType>
using a lambda expression. Before the =>
you type a declaration for the input parameters, after the =>
you call the function with these input parameters. If you have more than one input parameter you make them comma separated surrounded by brackets.
For a Where
you need a Func<TSource, bool>
. So a function that has as input one source element, and as result a bool:
Where(x => x.Name == "John Doe")
For a GroupJoin you need a resultSelector of type Func<TOuter,System.Collections.Generic.IEnumerable<TInner>,TResult> resultSelector
So this is a function with as input one element of the outer sequence, and a sequence of elements of the inner sequence. For example, to query Teachers with their Students:
var result = Teachers.GroupJoin(Students,
teacher => teacher.Id, // from every Teacher take the Id,
student => student.TeacherId, // from every Student take the TeacherId,
(teacher, students) => new
{
Id = teacher.Id,
Name = teacher.Name,
Students = students.Select(student => new
{
Id = student.Id,
Name = student.Name,
})
.ToList(),
});
Here you see several Funcs. TOuter is Teacher, TInner is Student, TKey is int
- OuterKeySelector:
Func<TOuter, TKey>
: teacher => teacher.Id
- InnerKeySelector:
Func<TInner, TKey>
: student => student.TeacherId
- ResultSelector:
Func<Touter, IEnumerable<TInner>, TResult>
The resultSelector is a function that takes one TOuter (a Teacher), and a sequence of TInner (all students of this Teacher) and creates one object using the input parameters
(teacher, students) => new {... use teacher and students }
When creating the lambda expression it is often helpful if you use plurals to refer to collections (teachers, students) and singulars if you refer one element of a collection (student).
Use the =>
to start defining the func. You can use input parameters that were defined before the =>
to define the result after the =>