C# LINQ

LINQ (Language Integrated Query) lets you query, filter, sort, and transform data using a readable, SQL-like syntax directly in C#. It works on arrays, lists, XML, databases, and any collection that implements IEnumerable.

Why LINQ?

┌──────────────────────────────────────────────────────────────┐
│  WITHOUT LINQ — manual loop logic:                           │
│                                                              │
│  List<int> result = new List<int>();                         │
│  foreach (int n in numbers)                                  │
│      if (n > 10)                                             │
│          result.Add(n);                                      │
│  result.Sort();                                              │
│                                                              │
│  WITH LINQ — declarative one-liner:                          │
│                                                              │
│  var result = numbers.Where(n => n > 10).OrderBy(n => n);    │
└──────────────────────────────────────────────────────────────┘

Two LINQ Syntax Styles

LINQ offers two equivalent styles — Method Syntax (fluent) and Query Syntax (SQL-like). Both produce identical results.

int[] numbers = { 5, 12, 3, 20, 8, 17, 1 };

// Method syntax (most common in practice):
var result1 = numbers.Where(n => n > 10).OrderBy(n => n);

// Query syntax (SQL-like):
var result2 = from n in numbers
              where n > 10
              orderby n
              select n;

// Both give: { 12, 17, 20 }

Core LINQ Methods

Where — Filter

List<string> names = new List<string>() { "Alice", "Bob", "Carol", "Dave", "Eve" };

var shortNames = names.Where(n => n.Length <= 3);
// [Bob, Eve]

var startsWithC = names.Where(n => n.StartsWith("C"));
// [Carol]

Select — Transform

int[] scores = { 80, 90, 70, 95 };

var doubled = scores.Select(s => s * 2);
// [160, 180, 140, 190]

var graded = scores.Select(s => s >= 90 ? "A" : s >= 80 ? "B" : "C");
// ["B", "A", "C", "A"]

OrderBy and OrderByDescending

var sorted    = scores.OrderBy(s => s);             // ascending
var sortedDesc = scores.OrderByDescending(s => s);  // descending

List<string> words = new List<string>() { "Banana", "Apple", "Cherry" };
var alpha = words.OrderBy(w => w);       // [Apple, Banana, Cherry]
var byLen  = words.OrderBy(w => w.Length); // [Apple, Banana, Cherry]

First, Last, Single

int[] data = { 3, 7, 2, 9, 4 };

Console.WriteLine(data.First());                // 3
Console.WriteLine(data.Last());                 // 4
Console.WriteLine(data.First(n => n > 5));     // 7
Console.WriteLine(data.FirstOrDefault(n => n > 100)); // 0 (default — no match)

Count, Sum, Average, Min, Max

int[] values = { 10, 20, 30, 40, 50 };

Console.WriteLine(values.Count());    // 5
Console.WriteLine(values.Sum());      // 150
Console.WriteLine(values.Average());  // 30
Console.WriteLine(values.Min());      // 10
Console.WriteLine(values.Max());      // 50

// With condition:
Console.WriteLine(values.Count(v => v > 25));  // 3
Console.WriteLine(values.Sum(v => v * 2));      // 300

Any and All

int[] nums = { 2, 4, 6, 7, 8 };

Console.WriteLine(nums.Any(n => n % 2 != 0));   // True  — at least one odd
Console.WriteLine(nums.All(n => n % 2 == 0));   // False — not all even (7 is odd)
Console.WriteLine(nums.Any());                   // True  — list is not empty

Skip and Take

int[] pages = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

var page2 = pages.Skip(3).Take(3);   // skip first 3, take next 3
// [4, 5, 6]

// Pagination example:
int pageSize   = 5;
int pageNumber = 2;   // 1-based

var pageData = pages.Skip((pageNumber - 1) * pageSize).Take(pageSize);
// [6, 7, 8, 9, 10]

Distinct and GroupBy

int[] withDups = { 1, 2, 2, 3, 3, 3, 4 };
var unique = withDups.Distinct();
// [1, 2, 3, 4]

// GroupBy:
string[] words = { "cat", "car", "bat", "bar", "ant" };
var groups = words.GroupBy(w => w[0]);   // group by first letter

foreach (var group in groups)
{
    Console.WriteLine($"Letter '{group.Key}': " + string.Join(", ", group));
}
// Letter 'c': cat, car
// Letter 'b': bat, bar
// Letter 'a': ant

LINQ on Objects

class Product
{
    public string Name;
    public string Category;
    public double Price;
}

List<Product> products = new List<Product>()
{
    new Product { Name="Laptop",  Category="Electronics", Price=999 },
    new Product { Name="Phone",   Category="Electronics", Price=499 },
    new Product { Name="Desk",    Category="Furniture",   Price=250 },
    new Product { Name="Chair",   Category="Furniture",   Price=150 },
    new Product { Name="Monitor", Category="Electronics", Price=350 },
};

// Get all electronics sorted by price:
var electronics = products
    .Where(p => p.Category == "Electronics")
    .OrderBy(p => p.Price)
    .Select(p => $"{p.Name}: ${p.Price}");

foreach (var item in electronics) Console.WriteLine(item);
// Monitor: $350
// Phone: $499
// Laptop: $999

// Average price by category:
var avgByCategory = products
    .GroupBy(p => p.Category)
    .Select(g => new { Category = g.Key, Avg = g.Average(p => p.Price) });

foreach (var item in avgByCategory)
    Console.WriteLine($"{item.Category}: avg ${item.Avg}");
// Electronics: avg $616
// Furniture: avg $200

LINQ Data Pipeline Diagram

┌──────────────────────────────────────────────────────────────┐
│  Source Data                                                 │
│  [Laptop $999] [Phone $499] [Desk $250] [Chair $150]         │
│         │                                                    │
│         ▼  .Where(p => p.Price > 200)                        │
│  [Laptop $999] [Phone $499] [Desk $250]                      │
│         │                                                    │
│         ▼  .OrderBy(p => p.Price)                            │
│  [Desk $250] [Phone $499] [Laptop $999]                      │
│         │                                                    │
│         ▼  .Select(p => p.Name)                              │
│  ["Desk", "Phone", "Laptop"]                                 │
└──────────────────────────────────────────────────────────────┘

Query Syntax vs Method Syntax

// Query syntax:
var result = from p in products
             where p.Price > 300
             orderby p.Name
             select p.Name;

// Method syntax equivalent:
var result = products
    .Where(p => p.Price > 300)
    .OrderBy(p => p.Name)
    .Select(p => p.Name);

Quick Reference

┌─────────────────────────┬─────────────────────────────────────┐
│ Method                  │ Purpose                             │
├─────────────────────────┼─────────────────────────────────────┤
│ Where(condition)        │ Filter matching items               │
│ Select(transform)       │ Project / transform each item       │
│ OrderBy / OrderByDesc   │ Sort ascending / descending         │
│ First / Last            │ Get first or last item              │
│ FirstOrDefault          │ First match or default value        │
│ Count / Sum / Avg       │ Aggregate calculations              │
│ Min / Max               │ Smallest or largest value           │
│ Any / All               │ Check any/all match condition       │
│ Skip / Take             │ Pagination                          │
│ Distinct                │ Remove duplicates                   │
│ GroupBy                 │ Group items by key                  │
│ ToList / ToArray        │ Execute query into collection       │
└─────────────────────────┴─────────────────────────────────────┘

LINQ transforms how you think about data processing in C#. Instead of writing loops and conditionals manually, you describe what you want — and LINQ figures out how to get it. It is one of the most productive features in the language and is used in virtually every real-world C# application.

Leave a Comment

Your email address will not be published. Required fields are marked *