Select Projections
Vaibhav • September 11, 2025
Once you've filtered your data using where
clauses, the next step is often to
transform or reshape it. This is where the select
clause comes in. In LINQ,
select projections allow you to extract specific parts of each element, create new shapes, or
even build anonymous types on the fly. Whether you're working with simple lists or complex objects, select
gives you precise control over what your query returns.
What is a Projection?
A projection is the process of transforming each element in a collection into a new form. In LINQ, this is done
using the select
keyword (in query syntax) or the Select
method (in method syntax). You can project entire elements, single
properties, computed values, or even new anonymous objects.
List fruits = new List { "apple", "banana", "cherry" };
var lengths = from fruit in fruits
select fruit.Length;
This query projects the length of each fruit name. Instead of returning the fruit itself, it returns an integer representing the number of characters in each string.
Using select
in Method Syntax
Method syntax uses the Select
method to perform projections. It takes a lambda
expression that defines how each element should be transformed.
var lengths = fruits.Select(f => f.Length);
This is functionally identical to the query syntax example above. The lambda f => f.Length
tells LINQ to return the length of each fruit string.
Projecting Entire Elements
Sometimes you want to return the entire element, possibly after filtering. This is the simplest form of projection.
var result = from fruit in fruits
where fruit.Contains("a")
select fruit;
This query filters fruits that contain the letter “a” and then selects the whole fruit string. The projection doesn’t change the shape - it just passes the element through.
Projecting Specific Properties
When working with custom types, you often want to extract specific properties. Suppose you have a list of products:
class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
List products = new List
{
new Product { Name = "Laptop", Price = 999.99m },
new Product { Name = "Tablet", Price = 499.50m },
new Product { Name = "Phone", Price = 799.00m }
};
var names = from p in products
select p.Name;
This query projects only the Name
property of each product. The result is a
list of strings containing product names.
Creating Anonymous Types
LINQ allows you to create anonymous types - objects with properties but no explicit class - directly in your query. This is useful when you want to shape data temporarily for display or further processing.
var summaries = from p in products
select new { p.Name, p.Price };
Each element in summaries
is an anonymous object with two properties: Name
and Price
. You can access them like regular
properties: item.Name
, item.Price
.
Computed Projections
You can also compute values during projection. For example, let’s calculate discounted prices:
var discounts = from p in products
select new { p.Name, Discounted = p.Price * 0.9m };
This query creates a new anonymous object with the product name and a discounted price (10% off). The Discounted
property is computed inline.
Using let
with select
The let
keyword allows you to introduce intermediate variables in query syntax.
This is helpful when the projection involves multiple steps or repeated expressions.
var result = from fruit in fruits
let upper = fruit.ToUpper()
select new { Original = fruit, Upper = upper };
Here, let
creates a variable upper
that stores
the uppercase version of each fruit. The select
clause then projects both the
original and transformed values.
Chaining Select
with Other LINQ Methods
Projections are often used in combination with filtering, sorting, and grouping. Method syntax makes it easy to chain these operations fluently.
var result = products
.Where(p => p.Price > 500)
.OrderBy(p => p.Name)
.Select(p => new { p.Name, p.Price });
This query filters products with a price above 500, sorts them by name, and then projects name and price into an anonymous type.
Projecting into Existing Types
While anonymous types are convenient, sometimes you want to project into a known class. This is useful when you need to pass the result to other parts of your program.
class ProductSummary
{
public string Name { get; set; }
public decimal Price { get; set; }
}
var summaries = products.Select(p => new ProductSummary
{
Name = p.Name,
Price = p.Price
});
This query creates a new ProductSummary
object for each product. The result is
a list of strongly-typed objects.
Flattening Nested Collections
Sometimes your data contains nested collections, and you want to flatten them. This is done using SelectMany
, which projects each element into a collection and then flattens the
result.
List wordGroups = new List
{
new[] { "apple", "apricot" },
new[] { "banana", "blueberry" },
new[] { "cherry" }
};
var allWords = wordGroups.SelectMany(group => group);
This query flattens the nested arrays into a single sequence of words. Instead of returning a list of arrays, it returns a list of strings.
Avoiding Common Mistakes
A common mistake is forgetting that select
creates a new shape. If you project
only part of an object, you lose access to the rest unless you include it explicitly. Also, avoid projecting
into anonymous types if you need to return the result from a method - use named types instead.
Use anonymous types for temporary shaping and display logic. For reusable data structures, project into named classes to maintain clarity and type safety.
Performance Considerations
Projections are generally efficient, but be mindful of what you compute inside select
. Avoid expensive operations or method calls unless necessary. Also,
remember that LINQ uses deferred execution - the projection doesn’t happen until you enumerate the result.
Note: If your projection involves multiple steps or external dependencies, consider materializing the result
early using ToList()
to avoid repeated computation.
Using Index in Projections
The method syntax version of Select
has an overload that provides the index of
each element. This is useful when you want to include position-based logic.
var indexed = fruits.Select((fruit, index) => new { Index = index, Name = fruit });
This query creates an anonymous object with the index and name of each fruit. It’s helpful for display or debugging purposes.
Summary
Select projections are a core part of LINQ. They allow you to reshape, transform, and extract data in a way
that’s both expressive and efficient. Whether you’re projecting simple values, creating anonymous types, or
building new objects, select
gives you the flexibility to control your query
output. By mastering projections, you’ll write cleaner, more focused LINQ queries that align with your
application’s needs.
In the next article, we’ll explore OrderBy and Sorting - how to organize your data using LINQ’s powerful sorting capabilities.