BlackWaspTM
LINQ
.NET 3.5+

LINQ Projection (2)

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.

Projecting into Anonymous Types

When you wish to obtain more than one field or property from a source collection it is common to project into an anonymous type. You can do this by using a delegate that returns an anonymous type and ensuring that the results of the query are assigned to an implicitly typed variable.

The following code shows a simple example. In this case the name and title for each result is combined into an anonymous type.

var namesAndTitles = employees.Select(e => new { e.Name, e.Title });

/* RESULTS

{ Name = Bob, Title = Senior Developer }
{ Name = Sam, Title = Developer }
{ Name = Mel, Title = Developer }
{ Name = Jim, Title = Junior Programmer }

*/

As you may expect, you can also assign names to the properties of the anonymous type by providing them within the braces following the new keyword. In the next sample, the names of the properties in the results are different to those in the source data:

var namesAndTitles = employees.Select(e => new { Employee = e.Name, Job = e.Title });

/* RESULTS

{ Employee = Bob, Job = Senior Developer }
{ Employee = Sam, Job = Developer }
{ Employee = Mel, Job = Developer }
{ Employee = Jim, Job = Junior Programmer }

*/

NB: Using similar code you can project into a collection of a known type, either by passing values to the constructor or by using object initializers.

Projections with Calculations

For the final example of projection using the Select standard query operator, we will include additional operations for the resultant values, again holding the results in an anonymous type. This is particularly useful when you wish to perform the same calculation upon each of the results. The calculations are included within the object initializer for the anonymous type.

In the example, each result contains three properties. The first is a string containing the name and job title for each employee, concatenated using the String.Format method. The second property is the employee's current salary and the final member contains a proposed new salary, being five percent higher than the existing value.

var salaryIncrease = employees.Select(e =>
    new {
        Employee = string.Format("{0}/{1}", e.Name, e.Title),
        e.Salary,
        NewSalary = e.Salary * 1.05
    });
 
/* RESULTS

{ Employee = Bob/Senior Developer, Salary = 40000, NewSalary = 42000 }
{ Employee = Sam/Developer, Salary = 32000, NewSalary = 33600 }
{ Employee = Mel/Developer, Salary = 29000, NewSalary = 30450 }
{ Employee = Jim/Junior Programmer, Salary = 20000, NewSalary = 21000 }

*/
>5 July 2010