<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. C#
  3. Functional C# and LINQ
All lessons in this course

Lesson 41 of 60 15 minIntermediate

LINQ basics: Where, Select, OrderBy

Query collections like a database: filter, sort, transform, take and summarise data in a few readable lines.

LINQ (Language Integrated Query) lets you ask questions about collections: “all IPE300 beams longer than 6 m, heaviest first, top 3”. Instead of writing loops with ifs and temporary lists, you describe what you want and LINQ does the looping.

Interactive

Build a LINQ query

var result = beams
.Where(b => b.Length > 5)
.OrderByDescending(b => b.Kg)
.Select(b => new { b.Mark, b.Kg })
.Take(3)
.ToList();
MarkKg
B4338
B3305
B7274

Loop vs LINQ

Compare.cs
// With a loopvar marks1 = new List<string>();foreach (var b in beams)    if (b.Length > 6)        marks1.Add(b.Mark);marks1.Sort(); // With LINQ: same result, and it reads like the requirementvar marks2 = beams    .Where(b => b.Length > 6)    .Select(b => b.Mark)    .OrderBy(m => m)    .ToList();

The core operators

OperatorDoesExample
Wherekeep items that pass a test.Where(b => b.Level == 2)
Selecttransform each item.Select(b => b.Mark)
OrderBy / OrderByDescendingsort by a key.OrderByDescending(b => b.Kg)
ThenBysecond sort key.OrderBy(b => b.Level).ThenBy(b => b.Mark)
Take / Skipfirst n / skip n (paging).Skip(20).Take(10)
Distinctremove duplicates.Select(b => b.Profile).Distinct()
ToList / ToArrayrun the query and store results.ToList()

Single results and checks

Single.cs
Beam? first = beams.FirstOrDefault(b => b.Profile == "HEA200");   // null if nonebool anyHeavy = beams.Any(b => b.Kg > 300);bool allValid = beams.All(b => b.Length > 0);int count = beams.Count(b => b.Level == 1); double totalKg = beams.Sum(b => b.Kg);double avgLen = beams.Average(b => b.Length);double longest = beams.Max(b => b.Length);Beam heaviest = beams.MaxBy(b => b.Kg)!;                            // .NET 6+ Console.WriteLine($"{count} on level 1, {totalKg} kg total, heaviest {heaviest.Mark}");
Output
3 on level 1, 1773 kg total, heaviest B4

Anonymous types in Select

Anonymous.cs
var report = beams    .Where(b => b.Level == 2)    .Select(b => new { b.Mark, Tonnes = b.Kg / 1000.0 });   // a type made on the fly foreach (var r in report)    Console.WriteLine($"{r.Mark}: {r.Tonnes:F3} t");
Output
B4: 0.338 t
B5: 0.067 t
B6: 0.233 t

Query syntax

LINQ also has an SQL-like syntax. It compiles to the same method calls; most teams use the method syntax, but you will see both.

QuerySyntax.cs
var q = from b in beams        where b.Length > 6        orderby b.Kg descending        select b.Mark;
Quick check

What does .Select(b => b.Mark) return for a list of beams?

Quick check

Which call is safe when no beam matches?

Practice

From int[] scores = { 72, 45, 90, 61, 88, 39, 77 };, use LINQ to print: the passing scores (≥ 50) sorted highest first, how many failed, and the average of the passing scores to 1 decimal.

Show the solution
Solution.cs
int[] scores = { 72, 45, 90, 61, 88, 39, 77 }; var passed = scores.Where(s => s >= 50).OrderByDescending(s => s).ToList();int failed = scores.Count(s => s < 50); Console.WriteLine(string.Join(", ", passed));Console.WriteLine($"Failed: {failed}");Console.WriteLine($"Average pass: {passed.Average():F1}");
Output
90, 88, 77, 72, 61
Failed: 2
Average pass: 77.6

Remember

  • LINQ queries collections with Where, Select, OrderBy, Take…
  • Chain operators; finish with ToList() to get a stored result.
  • Use Any, Count, Sum, Average, Max, MaxBy for answers.
  • Prefer FirstOrDefault when nothing may match.
0 of 60 lessons completed