100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C#

Projection with Select

Learn how LINQ's Select operator transforms each element of a sequence into a new shape, including anonymous types, the indexed overload, and how it differs from SelectMany.

Core OperatorsBeginner9 min readJul 10, 2026
Analogies

What Is Projection?

Select() transforms each element of a source sequence into a new form by applying a Func<TSource, TResult> to every item, producing an IEnumerable<TResult> that can have a completely different shape than the input — for example, projecting a sequence of Order objects down to just their Total values, or up into a richer object combining fields from multiple sources. Like Where(), Select() is deferred: the transformation function runs once per element only as the result is enumerated, not when Select() is called.

🏏

Cricket analogy: A scoreboard operator converting each ball bowled into a single display value (runs scored) transforms raw delivery data into a simpler shape, just as Select() maps each Order into just its Total.

Select vs. SelectMany

Select() preserves the sequence's cardinality — one input element produces exactly one output element, so projecting a List<Order> where each Order has a List<LineItem> with Select(o => o.LineItems) yields a sequence of sequences (IEnumerable<List<LineItem>>). SelectMany(), by contrast, flattens: it projects each element into an inner sequence and then concatenates all those inner sequences into a single flat result, so SelectMany(o => o.LineItems) over the same orders yields one combined IEnumerable<LineItem> across all orders.

🏏

Cricket analogy: Listing each match's set of scorecards as separate nested groups (Match 1's scorecards, Match 2's scorecards) is like Select(), while merging every scorecard across every match into one long flat list is like SelectMany().

Anonymous Types and Reshaping Data

A very common Select() pattern projects into an anonymous type, combining fields from the source object (and sometimes computed values) into a lightweight, purpose-built shape: orders.Select(o => new { o.Id, o.CustomerName, DaysAgo = (DateTime.Now - o.PlacedOn).Days }). Anonymous types are compiler-generated, immutable, and only usable within the method where they're created (or as var in the same scope), which makes them ideal for shaping data for display or serialization without defining a dedicated class just for that one query.

🏏

Cricket analogy: Building a custom scoreboard widget that combines a player's name, today's runs, and a computed strike rate into one bespoke display object mirrors how Select() projects into an anonymous type combining multiple fields plus a calculation.

The Indexed Select Overload

Select() also has an indexed overload, Select((item, index) => ...), which is useful when the output needs to know its position in the sequence — for example, numbering rows for display (Select((item, i) => new { Row = i + 1, item.Name })). As with the indexed Where() overload, this generally only works reliably against in-memory IEnumerable<T> sources; most IQueryable providers cannot translate the index parameter and will throw a NotSupportedException if used against a database query.

🏏

Cricket analogy: Numbering each ball in an over for a delivery-by-delivery commentary log (Ball 1, Ball 2...) requires knowing each ball's position, just like Select((ball, i) => ...) attaches the index to each projected element.

csharp
var orders = new List<Order>
{
    new Order { Id = 1, CustomerName = "Ada", PlacedOn = DateTime.Now.AddDays(-3), LineItems = new List<LineItem> { new LineItem("Widget", 2), new LineItem("Gadget", 1) } },
    new Order { Id = 2, CustomerName = "Grace", PlacedOn = DateTime.Now.AddDays(-1), LineItems = new List<LineItem> { new LineItem("Gizmo", 5) } },
};

// Simple projection: extract one field
var customerNames = orders.Select(o => o.CustomerName);

// Projection into an anonymous type with a computed value
var summaries = orders.Select(o => new
{
    o.Id,
    o.CustomerName,
    DaysAgo = (DateTime.Now - o.PlacedOn).Days
});

// Select produces nested sequences; SelectMany flattens across all orders
var nestedLineItems = orders.Select(o => o.LineItems);        // IEnumerable<List<LineItem>>
var allLineItems = orders.SelectMany(o => o.LineItems);        // IEnumerable<LineItem>

// Indexed overload for row numbering
var numbered = orders.Select((o, i) => new { Row = i + 1, o.CustomerName });

In query syntax, 'select' is the terminal clause of a query expression: from o in orders where o.Total > 50 select o.CustomerName. Every query expression must end in either a select clause or a group clause — this is why Select() and GroupBy() are sometimes called the 'result selectors' of LINQ.

Projecting entity objects directly from an ORM query (e.g., dbContext.Orders.Select(o => new { o.Customer.Name })) can trigger the notorious N+1 query problem if the projection touches a related entity that wasn't eagerly loaded — each access to o.Customer may issue a separate database round trip per order. Projecting only the columns you need directly in the Select() (letting the provider translate it into a single SQL query with a JOIN) is usually far more efficient than materializing full entities first.

  • Select() transforms each element of a sequence via a Func<TSource, TResult>, preserving one-to-one cardinality.
  • SelectMany() flattens: it projects each element to an inner sequence and concatenates all inner sequences into one flat result.
  • Select() is commonly used to project into anonymous types combining source fields with computed values.
  • The indexed Select() overload exposes each element's position but rarely translates to SQL for IQueryable sources.
  • Query syntax's terminal 'select' clause compiles to a Select() method call.
  • Projecting related entities from an ORM without eager loading can trigger the N+1 query problem.
  • Like Where(), Select() uses deferred execution — the transformation runs only when the query is enumerated.

Practice what you learned

Was this page helpful?

Topics covered

#LINQStudyNotes#MicrosoftTechnologies#ProjectionWithSelect#Projection#Select#SelectMany#Anonymous#StudyNotes#SkillVeris#ExamPrep