How to use LINQ Select in C# (projection examples)

The LINQ Select() method projects each element of a sequence into a new form. It transforms (maps) every item in a collection and returns a new IEnumerable<T> with the results.

Select() uses deferred execution — it doesn't run until you iterate the result or call .ToList(), .ToArray(), etc.

Unlike Where(), which filters, Select() always returns the same number of elements as the source.

Basic Projection

C# Example Code
var numbers = new List<int> { 1, 2, 3, 4, 5 };

// Square each number
var squares = numbers.Select(n => n * n);
Console.WriteLine(string.Join(", ", squares));
// Output: 1, 4, 9, 16, 25

Select a Single Property

C# Example Code
var people = new List<Person>
{
    new Person("Alice", 30),
    new Person("Bob", 25),
    new Person("Charlie", 35)
};

// Extract only the names
var names = people.Select(p => p.Name);
Console.WriteLine(string.Join(", ", names));
// Output: Alice, Bob, Charlie

class Person(string Name, int Age)
{
    public string Name { get; } = Name;
    public int Age { get; } = Age;
}

Select into an Anonymous Type

C# Example Code
var people = new List<Person>
{
    new Person("Alice", 30),
    new Person("Bob", 25),
    new Person("Charlie", 35)
};

// Project into a new shape
var summary = people.Select(p => new
{
    p.Name,
    IsAdult = p.Age >= 18,
    Label = $"{p.Name} ({p.Age})"
});

foreach (var s in summary)
    Console.WriteLine($"{s.Label} — adult: {s.IsAdult}");

// Output:
// Alice (30) — adult: True
// Bob (25) — adult: True
// Charlie (35) — adult: True

Select into a New Type (DTO Pattern)

C# Example Code
// Source model
var products = new List<Product>
{
    new Product(1, "Laptop", 999.99m),
    new Product(2, "Mouse", 29.99m),
    new Product(3, "Keyboard", 79.99m)
};

// Map to a lightweight DTO
var dtos = products
    .Select(p => new ProductDto(p.Id, p.Name))
    .ToList();

foreach (var dto in dtos)
    Console.WriteLine($"Id: {dto.Id}, Name: {dto.Name}");

record Product(int Id, string Name, decimal Price);
record ProductDto(int Id, string Name);

Select with Index

C# Example Code
var fruits = new List<string> { "apple", "banana", "cherry" };

// Include position in projection
var indexed = fruits.Select((fruit, index) => $"{index + 1}. {fruit}");
Console.WriteLine(string.Join("\n", indexed));

// Output:
// 1. apple
// 2. banana
// 3. cherry

SelectMany — Flatten Nested Collections

Use SelectMany() when each element contains a nested collection and you want a flat result.

C# Example Code
var orders = new List<Order>
{
    new Order("Alice", new[] { "Laptop", "Mouse" }),
    new Order("Bob",   new[] { "Keyboard" }),
    new Order("Charlie", new[] { "Monitor", "Webcam", "Headset" })
};

// Flatten all items from all orders into one sequence
var allItems = orders.SelectMany(o => o.Items);
Console.WriteLine(string.Join(", ", allItems));
// Output: Laptop, Mouse, Keyboard, Monitor, Webcam, Headset

// SelectMany with result selector (include source)
var itemsWithOwner = orders.SelectMany(
    o => o.Items,
    (order, item) => $"{order.Customer}: {item}"
);
foreach (var entry in itemsWithOwner)
    Console.WriteLine(entry);

record Order(string Customer, string[] Items);

Method Syntax vs Query Syntax

C# Example Code
var numbers = new List<int> { 1, 2, 3, 4, 5 };

// Method syntax (most common)
var methodResult = numbers.Select(n => n * 2).ToList();

// Query syntax (SQL-like)
var queryResult = (from n in numbers
                   select n * 2).ToList();

Console.WriteLine(string.Join(", ", methodResult));
// Output: 2, 4, 6, 8, 10

Chaining Select with Other LINQ Methods

C# Example Code
var people = new List<Person>
{
    new Person("Alice", 30),
    new Person("Bob", 17),
    new Person("Charlie", 22),
    new Person("Dave", 15)
};

// Filter, project, and sort in one chain
var adultNames = people
    .Where(p => p.Age >= 18)
    .OrderBy(p => p.Name)
    .Select(p => p.Name.ToUpper())
    .ToList();

Console.WriteLine(string.Join(", ", adultNames));
// Output: ALICE, CHARLIE

Select vs SelectMany — Quick Comparison

SelectSelectMany
InputIEnumerable<T>IEnumerable<IEnumerable<T>>
OutputIEnumerable<TResult>IEnumerable<TResult> (flat)
Shape1-to-1 mapping1-to-many (flatten)
Use caseTransform each itemUnpack nested collections