How many times have you written a foreach loop with an if inside, just to pluck a few items out of a list? There's a better way. LINQ (Language Integrated Query) lets you filter, sort, group, and transform collections in C# with a few readable lines — and once it clicks, you'll never go back.

The old way vs. the LINQ way

Let's borrow the patients from our clinic system design series. Say we have a List<Patient> and we want everyone over 30. Here's the loop we've all written a hundred times:

var adults = new List<Patient>();
foreach (var patient in patients)
{
    if (patient.Age > 30)
    {
        adults.Add(patient);
    }
}

Seven lines. Now the LINQ version of the exact same task:

var adults = patients.Where(p => p.Age > 30).ToList();

One line, and it reads almost like English: "from patients, where the patient's age is over 30, make a list." The little arrow => creates a lambda — a tiny inline function that says "given a patient p, here's the test to apply."

The core four

LINQ has dozens of methods, but four of them do most of the daily work. Master these and you're dangerous.

Where — filter

Keeps only the items that pass a test:

var overdue = appointments.Where(a => a.Status == "Missed");

Select — transform

Turns each item into something else — like extracting just the names:

var names = patients.Select(p => p.Name).ToList();

OrderBy — sort

Sorts by whatever you point at:

var youngestFirst = patients.OrderBy(p => p.Age).ToList();

GroupBy — bucket

Splits a collection into groups that share a key, such as patients by city:

var byCity = patients.GroupBy(p => p.City);

foreach (var group in byCity)
{
    Console.WriteLine($"{group.Key}: {group.Count()} patients");
}

And when you're ready to explore further, there's a whole toolbox waiting:

WhereSelectOrderByGroupByFirstAnyAllCountSumAverageTakeSkipDistinct

Chains that read like sentences

The real magic starts when you connect the pieces. Each LINQ method returns a collection, so the next method can pick up right where the last one left off:

var report = appointments
    .Where(a => a.Status == "Completed")
    .OrderBy(a => a.Date)
    .Select(a => a.PatientName)
    .ToList();

Read it aloud: "From appointments, keep the completed ones, order them by date, take each patient's name, and make a list." The code is the explanation — no comments needed.

Note: LINQ uses deferred execution — building a query doesn't run it. The work happens when you enumerate the results, for example with foreach, ToList(), or Count(). Think of the query as a recipe; nothing gets cooked until someone orders the dish.

LINQ is SQL for your objects

If you've peeked at databases, this might all feel familiar — and that's no accident. LINQ brings the spirit of SQL queries to your in-memory collections:

LINQ methods and their SQL cousins
LINQ SQL What it does
Where WHERE Filters rows or items
Select SELECT Chooses or shapes what comes back
OrderBy ORDER BY Sorts the results
GroupBy GROUP BY Buckets by a shared key

So learning LINQ secretly prepares you for databases, too. Curious about that world? Start with SQL vs. NoSQL: which to learn first.

Tip: Not sure what a chain returns? Hover over the variable in your editor — the tooltip shows the exact type. It's a great way to check your understanding one link at a time.

Here's your homework: find one loop-with-an-if in your own code and rewrite it with Where. That first one-liner is addictive. New to the language itself? Here's why C# is a great first language — LINQ is one of its best perks. Happy querying!