The scenario: you have two related collections of objects, and you need to smush ’em together into a collection of combined records. It’s easy to do with LINQ’s Join method, but Join can seem a little intimidating–just check out its declaration:
// yikes! public static IEnumerable Join<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector )
It’s really not so bad, though. Here’s the breakdown:
- “this IEnumerable<TOuter> outer” what you’re joining from
- “IEnumerable<TInner> inner” what you’re joining to
- “Func<TOuter, TKey> outerKeySelector” an expression for how to match the ‘from’ records
- “Func<TInner, TKey> innerKeySelector” an expression for how to match the ‘to’ records
- “Func<TOuter, TInner, TResult> resultSelector” an expression for the joined result
Still sounds rough? Let’s look at an easy example:
class Person
{
public string Name;
public string Occupation;
}
class Job
{
public string Name;
public decimal Salary;
}
void Main()
{
var people = new[]
{
new Person { Name = "Adam", Occupation = "Blogger" },
new Person { Name = "Joe", Occupation = "Teacher" },
new Person { Name = "Hilary", Occupation = "Actress" }
};
var jobs = new[]
{
new Job { Name = "Blogger", Salary = 0.0m },
new Job { Name = "Teacher", Salary = 100.0m },
new Job { Name = "Actress", Salary = 5000.0m }
};
var salaryByPerson = people.Join(
jobs,
p => p.Occupation,
j => j.Name,
(p,j) => new { Person = p.Name, Salary = j.Salary });
foreach (var sbp in salaryByPerson)
{
Console.WriteLine("Person: {0}, Salary: {1}",
sbp.Person,
sbp.Salary.ToString("c"));
}
}
/* Output
Person: Adam, Salary: $0.00
Person: Joe, Salary: $100.00
Person: Hilary, Salary: $5,000.00
*/
The Join in the above example is equivalent to SQL like this:
SELECT p.Name AS Person, j.Salary FROM people p JOIN jobs j ON p.Occupation=j.Name
Now you’ve got it, right? Yea!