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.