# Common LINQ Methods

The LINQ methods you'll use every day. Where, OrderBy, ThenBy and Select filter, sort and reshape; Count, Sum, Average, Min, Max, Any, All and GroupBy summarize; First, FirstOrDefault, Take, Skip and Distinct pick items.

Journeyman · C# · Updated November 3, 2026

## After this lesson you can

- Filter, sort and reshape a collection with Where, OrderBy, ThenBy and Select
- Summarize a collection with Count, Sum, Average, Min, Max, Any, All and GroupBy
- Pick items from a collection with First, FirstOrDefault, Take, Skip and Distinct

## Key takeaways

- `Where` keeps the items you want, `OrderBy` and `ThenBy` sort them, and `Select` turns each item into something new, such as its name.
- `Count`, `Sum`, `Average`, `Min`, `Max`, `Any` and `All` end a chain with one value: `Any` asks about at least one item, `All` about every item.
- `GroupBy` sorts items into groups; each group has a `Key` and is itself a collection you can count and total.
- Use `First` when there must be a match, since it throws if there's none; use `FirstOrDefault` when none is a normal answer, then check for `null`.
- `Take(n)` gives the first `n` items, `Skip(n)` the rest and `Distinct()` drops duplicates. `Skip(10).Take(10)` is page 2 of a list shown 10 at a time.

LINQ has dozens of methods, but a handful do most of the work. Every example in this lesson uses the same small café menu:

```csharp
public class Product
{
    public string Name { get; }
    public string Category { get; }
    public decimal Price { get; }

    public Product(string name, string category, decimal price)
    {
        Name = name;
        Category = category;
        Price = price;
    }
}
```

```text
Coffee     Drinks   3.50
Tea        Drinks   2.75
Juice      Drinks   4.00
Croissant  Bakery   3.75
Muffin     Bakery   2.50
Bagel      Bakery   2.25
```

## Filter, sort and reshape

| Method | Does | Like SQL's |
|---|---|---|
| `Where(p => ...)` | Keeps the items the lambda is `true` for | `WHERE` |
| `OrderBy(p => ...)` | Sorts by what the lambda returns, smallest first | `ORDER BY` |
| `OrderByDescending(p => ...)` | Sorts largest first | `ORDER BY ... DESC` |
| `ThenBy(p => ...)` | Sorts items that tied in the sort before it | the second column of `ORDER BY` |
| `Select(p => ...)` | Turns each item into what the lambda returns | `SELECT` |

```csharp
List<Product> menu = new List<Product>
{
    new Product("Coffee", "Drinks", 3.50m),
    new Product("Tea", "Drinks", 2.75m),
    new Product("Juice", "Drinks", 4.00m),
    new Product("Croissant", "Bakery", 3.75m),
    new Product("Muffin", "Bakery", 2.50m),
    new Product("Bagel", "Bakery", 2.25m)
};

List<string> cheapest = menu
    .Where(p => p.Price < 3.00m)
    .OrderBy(p => p.Price)
    .Select(p => $"{p.Name} {p.Price:C}")
    .ToList();

foreach (string line in cheapest)
{
    Console.WriteLine(line);
}

Console.WriteLine();

foreach (Product p in menu.OrderBy(p => p.Category).ThenByDescending(p => p.Price))
{
    Console.WriteLine($"{p.Category}: {p.Name}");
}

public class Product
{
    public string Name { get; }
    public string Category { get; }
    public decimal Price { get; }

    public Product(string name, string category, decimal price)
    {
        Name = name;
        Category = category;
        Price = price;
    }
}
```

```text
Bagel $2.25
Muffin $2.50
Tea $2.75

Bakery: Croissant
Bakery: Muffin
Bakery: Bagel
Drinks: Juice
Drinks: Coffee
Drinks: Tea
```

`Select` can turn each product into anything: here, a line of text. `Select(p => p.Name)` would give just the names, and `Select(p => p.Price * 1.1m)` the prices with 10% added.

## Summarize

These end a chain with **one value**:

| Method | Returns |
|---|---|
| `Count()`, `Count(p => ...)` | How many items, or how many the lambda is `true` for |
| `Sum(p => ...)`, `Average(p => ...)` | The total, or the average, of what the lambda returns |
| `Min(p => ...)`, `Max(p => ...)` | The smallest, or the largest, of what the lambda returns |
| `Any(p => ...)` | `true` if the lambda is `true` for **at least one** item |
| `All(p => ...)` | `true` if the lambda is `true` for **every** item |

```csharp
List<Product> menu = new List<Product>
{
    new Product("Coffee", "Drinks", 3.50m),
    new Product("Tea", "Drinks", 2.75m),
    new Product("Juice", "Drinks", 4.00m),
    new Product("Croissant", "Bakery", 3.75m),
    new Product("Muffin", "Bakery", 2.50m),
    new Product("Bagel", "Bakery", 2.25m)
};

Console.WriteLine(menu.Count(p => p.Category == "Drinks"));
Console.WriteLine(menu.Sum(p => p.Price));
Console.WriteLine(menu.Average(p => p.Price));
Console.WriteLine(menu.Max(p => p.Price));
Console.WriteLine(menu.Any(p => p.Price > 5.00m));
Console.WriteLine(menu.All(p => p.Price > 2.00m));

public class Product
{
    public string Name { get; }
    public string Category { get; }
    public decimal Price { get; }

    public Product(string name, string category, decimal price)
    {
        Name = name;
        Category = category;
        Price = price;
    }
}
```

```text
3
18.75
3.125
4.00
False
True
```

### GroupBy

**`GroupBy`** sorts the items into groups by what the lambda returns, like SQL's `GROUP BY`. Each group has a **`Key`** (what its items share) and is itself a collection, so you can count and total it:

```csharp
List<Product> menu = new List<Product>
{
    new Product("Coffee", "Drinks", 3.50m),
    new Product("Tea", "Drinks", 2.75m),
    new Product("Juice", "Drinks", 4.00m),
    new Product("Croissant", "Bakery", 3.75m),
    new Product("Muffin", "Bakery", 2.50m),
    new Product("Bagel", "Bakery", 2.25m)
};

foreach (var group in menu.GroupBy(p => p.Category))
{
    Console.WriteLine($"{group.Key}: {group.Count()} items, from {group.Min(p => p.Price):C}");
}

public class Product
{
    public string Name { get; }
    public string Category { get; }
    public decimal Price { get; }

    public Product(string name, string category, decimal price)
    {
        Name = name;
        Category = category;
        Price = price;
    }
}
```

```text
Drinks: 3 items, from $2.75
Bakery: 3 items, from $2.25
```

(A group's full type is a mouthful, `IGrouping<string, Product>`, so `var` is the usual choice here. The groups come out in the order their first item appears.)

## Pick items

| Method | Returns |
|---|---|
| `First(p => ...)` | The first item the lambda is `true` for. **Throws** an `InvalidOperationException` if there's none. |
| `FirstOrDefault(p => ...)` | The same, but `null` (or `0`, for numbers) if there's none |
| `Take(n)`, `Skip(n)` | The first `n` items, or everything after the first `n` |
| `Distinct()` | The items with duplicates removed |

```csharp
List<Product> menu = new List<Product>
{
    new Product("Coffee", "Drinks", 3.50m),
    new Product("Tea", "Drinks", 2.75m),
    new Product("Juice", "Drinks", 4.00m),
    new Product("Croissant", "Bakery", 3.75m),
    new Product("Muffin", "Bakery", 2.50m),
    new Product("Bagel", "Bakery", 2.25m)
};

Console.WriteLine(menu.First(p => p.Category == "Bakery").Name);

Product? soup = menu.FirstOrDefault(p => p.Name == "Soup");
Console.WriteLine(soup == null ? "No soup today" : soup.Name);

List<string> topTwo = menu.OrderByDescending(p => p.Price).Take(2).Select(p => p.Name).ToList();
Console.WriteLine(string.Join(", ", topTwo));

List<string> categories = menu.Select(p => p.Category).Distinct().ToList();
Console.WriteLine(string.Join(", ", categories));

public class Product
{
    public string Name { get; }
    public string Category { get; }
    public decimal Price { get; }

    public Product(string name, string category, decimal price)
    {
        Name = name;
        Category = category;
        Price = price;
    }
}
```

```text
Croissant
No soup today
Juice, Croissant
Drinks, Bakery
```

Use `First` when there **must** be a match (if there isn't, something's wrong, and the exception says so), and `FirstOrDefault` when "none" is a normal answer, then check for `null`. `Skip` and `Take` together give pages: `Skip(10).Take(10)` is page 2 of a list shown 10 at a time.

## Check yourself

3 questions to try on the lesson page.

## So what

Filter with `Where`, sort with `OrderBy`, reshape with `Select`, summarize with `Count`, `Sum` and `GroupBy`, and pick with `First` and `Take`. Those few methods replace most of the loops you'd otherwise write.

## Key terms

- [Where()](https://www.ask-codey.com/glossary/where)
- [OrderBy()](https://www.ask-codey.com/glossary/orderby)
- [Select()](https://www.ask-codey.com/glossary/select)
- [GroupBy()](https://www.ask-codey.com/glossary/groupby)
- [FirstOrDefault()](https://www.ask-codey.com/glossary/firstordefault)

## Cheat sheets

- [Common LINQ Methods](https://www.ask-codey.com/cheat-sheets/linq-common-linq-methods-cheat-sheet)

Source: https://www.ask-codey.com/lessons/linq-common-linq-methods
