
.NET 3.5+LINQ Projection
The third part of the LINQ to Objects tutorial describes basic projection in LINQ using the Select standard query operator and the select clause. These allow the type of all of the values that are returned from a LINQ query to be specified.
Projection
In the first two parts of the LINQ to Objects Tutorial, we have seen queries executed using the standard query operators and query expression syntax. All of the queries so far have extracted values or objects from a type-safe collection and returned a generic IEnumerable of the same class or structure. This can often be the required functionality but sometimes you will wish to return values of an alternative type.
The process of transforming the results of a query is called projection. You can project the results of a query after any filters have been applied to change the type of the collection that is returned. For example, you can select a single property or field from the source data or project multiple properties into an anonymous type. You can also add calculations and other operations to the projection to generate information that is based upon the source data but not directly retrieved from it.
In this article we will see examples of projection using the Select standard query operator and the select clause. These give a single result for each item in the source data. You can also perform projection over multiple source collections in one-to-many relationships, flattening the hierarchy into a single set of results. This will be examined in the next article in the tutorial.
Select Operator
The Select standard query operator is an extension method of the IEnumerable<T> interface that requires a single parameter containing a Func delegate. The delegate is applied to each result of the overall query to project each item to the required type. To demonstrate the operator we need some sample data to work with. First, we will create a class that represents an employee. This is the same class that we used in the previous article:
public class Employee
{
public string Name { get; set; }
public string Title { get; set; }
public int Salary { get; set; }
public Employee(string name, string title, int salary)
{
Name = name;
Title = title;
Salary = salary;
}
public override string ToString()
{
return string.Format("{0}, {1} (£{2})", Name, Title, Salary);
}
}
We can now create a collection of employees to query:
var employees = new List<Employee>
{
new Employee("Bob", "Senior Developer", 40000),
new Employee("Sam", "Developer", 32000),
new Employee("Mel", "Developer", 29000),
new Employee("Jim", "Junior Programmer", 20000)
};
Simple Projection
For the first projection example, we will retrieve every item from the employees list. Instead of returning the entire employee object in each case, we will use a projection that extracts only the employees' names. This is achieved by using the Select operator with a Func delegate that returns the Name property of an employee, in this case defined using the lambda expression, "e => e.Name".
var names = employees.Select(e => e.Name);
/* RESULTS
Bob
Sam
Mel
Jim
*/
The Select operator can be combined with other standard query operators by chaining the methods together. In the following example, the names of all employees with a salary of more than £30,000 are included in the results. As with other operators that we have seen in the tutorial, the Select operator uses deferred execution. This means that the effects of the Where and Select operators are combined and executed as a single query when the results are first examined.
var names = employees.Where(e => e.Salary > 30000).Select(e => e.Name);
/* RESULTS
Bob
Sam
*/
>5 July 2010