CodeGym /Courses /C# SELF /Intro to LINQ and Why It Rocks

Intro to LINQ and Why It Rocks

C# SELF
Level 31 , Lesson 0
Available

1. Intro

Imagine you walk into a library and need to find all programming books published after 2020, sorted by the author's name. You probably wouldn't run from shelf to shelf checking every book by hand, right? You'd ask the librarian, who knows how to find what you need fast.

LINQ (Language Integrated Query) is our "smart librarian," a "SQL engine" (meaning, a tool for writing data queries) right inside C#!

Think of LINQ as a language that lets you describe what you want from your data, not how to get it. Instead of saying: "Take the first item, check the condition, if it fits, add it to a new list, then go to the next one...", you just say: "Give me all products with a price over 1000." And C# figures out the most efficient way to do it.

The key idea of LINQ: provide a standard syntax for queries to any data source that implements the IEnumerable<T> interface. And that's awesome, because List<T>, arrays, HashSet<T>—they all implement IEnumerable<T>. And if your data is in a database, special libraries (like Entity Framework) will turn your LINQ queries into real SQL!

LINQ showed up in C# over 10 years ago. It was a game-changer that totally changed how we work with data in .NET. Before LINQ, devs had to write a ton of boilerplate code for filtering, sorting, and transforming collections. Or use SQL query strings, which the compiler couldn't check and were prone to runtime errors. LINQ brought the concept of "queries" right into the programming language, making them type-safe and way more readable.

A lot of people think LINQ is one of the biggest things to happen to C# since generics (Generics) came along.

2. Why Everyone Loves LINQ: The Perks

Short and readable code: To filter, say, products with a price over 1000 in a big database, you used to write several lines of code. With LINQ, you can do it in one. Less code means fewer bugs and more readable, understandable code. It gets closer to natural language.
Programmer joke: "The less code I write, the fewer bugs I can sneak in." LINQ totally helps with that!

Power and flexibility: LINQ gives you a rich set of operations: filtering (Where), projection (Select), sorting (OrderBy), grouping (GroupBy), aggregation (Sum, Average), joining (Join), and a lot more. You can solve tough data processing tasks by combining these.

Type safety: This is super important! When you write a SQL query as a string, the compiler knows nothing about it. If you mess up a column name, you'll only find out at runtime when your app crashes. With LINQ, the C# compiler checks your query for errors right when you build. If you try to query a non-existent field on a Product object, the compiler will flag it instantly. It's like having your own personal spellchecker catching your typos before anyone else sees them.

Language integration: LINQ queries aren't some "magic" strings. They're full-blown C# constructs that use familiar lambda expressions and work with the data types you already know. That makes picking up LINQ super smooth.

Deferred Execution: This is one of the coolest—and maybe trickiest—concepts in LINQ, but it's really important. The idea is, a LINQ query doesn't run right away when you write it. It "builds up" and waits until you actually ask for the result (like when you start looping over it in a foreach). This lets LINQ optimize queries, especially with big data sets. We'll talk more about this in Lecture 166. For now, just remember: LINQ is smart, it doesn't do extra work.

Universal and extendable: LINQ isn't just for in-memory lists. There are different LINQ "providers":

  • LINQ to Objects: for in-memory collections (List<T>, arrays, etc.).
  • LINQ to SQL / Entity Framework Core: for SQL databases (your LINQ queries get turned into SQL).
  • LINQ to XML: for working with XML docs.
  • And lots more.
    That means, once you learn LINQ, you can work with data from all sorts of sources using the same query logic.

3. The Old-School Collection Handling Problem

Before LINQ, code for handling collections in C# looked something like this:


var products = new List<Product> { /* ... */ };

var expensive = new List<Product>();
foreach (var prod in products)
{
    if (prod.Price > 100)
        expensive.Add(prod);
}

expensive.Sort((a, b) => a.Price.CompareTo(b.Price));

foreach (var item in expensive)
    Console.WriteLine(item.Name);

This approach is typical: first filter by hand, then sort—always making an intermediate list. The more logic, the more code, bugs, and variables. It's like a furniture workshop: you've got the parts, but putting it all together is manual and exhausting.

Alice in Loopland

Imagine you have a huge list of users, and you want just the names of those over 18 who live in Neonville, sorted alphabetically, and show the first three. You'd have to write nested loops, conditions, sorts, helper lists... or just use LINQ.

4. What Does a LINQ Query Look Like? Simple Examples

LINQ gives you two main syntaxes:

  • Method Syntax (method chaining)
  • Query Syntax (SQL-like language)

Most of the time, people use Method Syntax, especially in modern projects. Here's an example from our app:


var expensive = products
    .Where(p => p.Price > 100)
    .OrderBy(p => p.Price)
    .Select(p => p.Name)
    .Take(3);

foreach (var name in expensive)
    Console.WriteLine(name);

It's all clear: filter, sort, pick a field, limit the count. Minimal code—maximum meaning.

The Same Thing with Query Syntax


var expensive = from p in products
                where p.Price > 100
                orderby p.Price
                select p.Name;

foreach (var name in expensive.Take(3))
    Console.WriteLine(name);

Both ways give you the same result—pick whichever you like best (but method syntax is used more often).

5. LINQ Architecture: What's Under the Hood?

LINQ works with any collections that implement the IEnumerable<T> interface (or IQueryable<T>, but we'll talk about that later).

Main LINQ Components

Component Short Description
LINQ Extension Classes Static methods (
Where
,
Select
,
OrderBy
, etc.) in the
System.Linq.Enumerable
class
Delegates Most often you'll use
Func<T, TResult>
and
Predicate<T>
Deferred Execution The query only runs when you first loop over it (like with
foreach
)
Query Provider (for LINQ to SQL, LINQ to Entities)—turns your method chain into SQL queries, etc.

Visual Diagram


Collection (List<Product>, T[], ...) 
      │
      ▼
LINQ methods (Where, OrderBy, Select...)
      │
      ▼
Query (IEnumerable<T>) 
      │
      ▼
Actual execution (foreach, ToList, Count, ...)

6. Example: Step-by-Step LINQ Chain in Our App

Back to our mini-app with the Product class:


// Product class
class Product
{
    public string Name { get; set; }
    public double Price { get; set; }
}

Here's a set of products:


var products = new List<Product>
{
    new Product { Name = "Cheese", Price = 250.5 },
    new Product { Name = "Bread", Price = 30 },
    new Product { Name = "Milk", Price = 80 },
    new Product { Name = "Coffee", Price = 330 },
    new Product { Name = "Butter", Price = 140 }
};

Let's say our task is: print the names of all products over 100 euros, sorted by price.

The Old Way


var filtered = new List<Product>();
foreach (var p in products)
{
    if (p.Price > 100)
        filtered.Add(p);
}

filtered.Sort((a, b) => a.Price.CompareTo(b.Price));

foreach (var p in filtered)
    Console.WriteLine(p.Name);

The LINQ Way


var expensive = products
    .Where(p => p.Price > 100)
    .OrderBy(p => p.Price)
    .Select(p => p.Name);

foreach (var name in expensive)
    Console.WriteLine(name);

In the first line, we're describing the heart of the task: "Filter those with Price > 100, sort by price, pick the names."

7. Common LINQ Operations and Their Old-School Analogs

Operation Old-School Logic LINQ
Filtering foreach + if + Add
Where
Projection (pick a field) foreach + Add(field)
Select
Sorting Sort(comparer)
OrderBy
,
OrderByDescending
Unique values foreach + contains + Add
Distinct
Counting foreach + counter++
Count
,
Count(predicate)
Condition check foreach + if
Any
,
All
Find first/last foreach + if + break
First
,
Last
,
FirstOrDefault
Limit count foreach + counter + break
Take
,
Skip

8. Practice: Adding LINQ to the App

Let's grab the basic code from our app (Product list) and try out a few handy operations with LINQ.

Filtering and Sorting


// Pick products cheaper than 200 euros and sort by name
var cheapProducts = products
    .Where(p => p.Price < 200)
    .OrderBy(p => p.Name);

foreach (var p in cheapProducts)
    Console.WriteLine($"{p.Name}: {p.Price} euros");

Collection Transformation (Projection)


// Get a list of prices (double)
var prices = products.Select(p => p.Price);

foreach (var price in prices)
    Console.WriteLine(price);

Find the First Matching Element


// First product whose name starts with "C"
var firstK = products.FirstOrDefault(p => p.Name.StartsWith("C"));
Console.WriteLine(firstK?.Name ?? "Not found");

Count Products Over 100 Euros


int count = products.Count(p => p.Price > 100);
Console.WriteLine($"There are: {count} items.");

Starting with this lecture, we're going to use LINQ a lot for handling collections, filtering, picking the data you need, aggregations, and a bunch more. We'll check out new LINQ methods and features (including .NET 9 goodies!) in upcoming lectures, but for now—don't be shy, play around with simple queries to feel the power of this tool!

2
Task
C# SELF, level 31, lesson 0
Locked
Filtering numbers from an array
Filtering numbers from an array
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION