You can reuse Linq Select functions by defining a delegate Func field that can be used in multiple Linq queries.
I had a few Linq to Objects queries that were querying the same collection but had different Where clauses that were nested between various if statements. The similarity between all of these statements was the Select function. This was quite long itself and it was annoying seeing such repetition. DRY!
So I tried to create a Func parameter that I could just pass into my Select statement which previously, for example could look like this:
ReturningPerson person; if (iFeelLikeIt) { person = people.Where(person => person.IsNameFunny) .Select(person => new ReturningPerson { DateOfBirth = input.DateBorn, Name = string.Format("{0} {1}", input.FirstName, input.LastName), AwesomenessLevel = input.KnowsLinq ? "High" : "Must try harder", CanFlyJet = false }) .FirstOrDefault(); } else { person = people.Where(person => person.Toes == 10) .Select(person => new ReturningPerson { DateOfBirth = input.DateBorn, Name = string.Format("{0} {1}", input.FirstName, input.LastName), AwesomenessLevel = input.KnowsLinq ? "High" : "Must try harder", CanFlyJet = false }) .FirstOrDefault(); }
This could be modified to work like this:
Expression<Func<InputPerson, ReturningPerson>> selector = (input) => new ReturningPerson { DateOfBirth = input.DateBorn, Name = string.Format("{0} {1}", input.FirstName, input.LastName), AwesomenessLevel = input.KnowsLinq ? "High" : "Must try harder", CanFlyJet = false }; ReturningPerson person; if (iFeelLikeIt) { person = people.Where(person => person.IsNameFunny) .Select(selector) .FirstOrDefault(); } else { person = people.Where(person => person.Toes == 10) .Select(selector) .FirstOrDefault(); }