LINQ — Language Integrated Query
LINQ är ett av C#:s kraftfullaste verktyg. Det låter dig filtrera, transformera och aggregera samlingar med en konsekvent syntax — oavsett om du jobbar med listor, arrayer, databaser eller XML.
När du läst detta ska du kunna
- Använda
Where,Select,OrderBy,GroupBy,First,Any,Count - Kedja LINQ-metoder (method chaining)
- Förstå skillnaden mellan lazy evaluation och
ToList() - Skriva LINQ mot egna klasser
Grundläggande metoder
var number = new List<int> { 5, 2, 8, 1, 9, 3, 7, 4, 6 };Where — filtrera
var large = number.Where(t => t > 5).ToList();// [8, 9, 7, 6]Select — transformera
var squares = number.Select(t => t * t).ToList();// [25, 4, 64, 1, 81, 9, 49, 16, 36]OrderBy / OrderByDescending
var sorted = number.OrderBy(t => t).ToList();// [1, 2, 3, 4, 5, 6, 7, 8, 9]
var reverse = number.OrderByDescending(t => t).ToList();// [9, 8, 7, 6, 5, 4, 3, 2, 1]Aggregat
Console.WriteLine(number.Sum()); // 45Console.WriteLine(number.Max()); // 9Console.WriteLine(number.Min()); // 1Console.WriteLine(number.Average()); // 5Console.WriteLine(number.Count()); // 9First / Last / Single
Console.WriteLine(number.First()); // 5Console.WriteLine(number.First(t => t > 7)); // 8Console.WriteLine(number.Load()); // 6Console.WriteLine(number.FirstOrDefault(t => t > 100)); // 0 (default int)Any / All / Contains
Console.WriteLine(number.Any(t => t > 8)); // TrueConsole.WriteLine(number.All(t => t > 0)); // TrueConsole.WriteLine(number.Contains(7)); // TrueLINQ mot egna klasser
public class Student{ public string Name { get; set; } public int Grade { get; set; }}
var students = new List<Student>{ new() { Name = "Anna", Grade = 5 }, new() { Name = "Björn", Grade = 3 }, new() { Name = "Clara", Grade = 5 }, new() { Name = "David", Grade = 4 },};
// Alla med betyg 5, sorterade på namnvar topList = students .Where(s => s.Grade == 5) .OrderBy(s => s.Name) .Select(s => s.Name) .ToList();
foreach (var name in topList) Console.WriteLine(name);Output
AnnaClaraGroupBy — gruppera
var grupperadePerBetyg = students .GroupBy(s => s.Grade) .OrderByDescending(g => g.Key);
foreach (var group in grupperadePerBetyg){ Console.Write($"Betyg {group.Key}: "); Console.WriteLine(string.Join(", ", group.Select(s => s.Name)));}Output
Grade 5: Anna, ClaraGrade 4: DavidGrade 3: BjörnTake och Skip — paginering
var page = students.OrderBy(s => s.Name).Take(2).ToList();var page = students.OrderBy(s => s.Name).Skip(2).Take(2).ToList();Distinct och Union
var med = new List<int> { 1, 2, 2, 3, 3, 3 };var unique = med.Distinct().ToList(); // [1, 2, 3]Lazy evaluation — viktigt!
LINQ-frågor körs inte förrän du itererar över resultatet. ToList() tvingar exekvering direkt.
var question = number.Where(t => t > 5); // ingen beräkning än
number.Add(99);
var result = question.ToList(); // körs nu — 99 är med!Anropa alltid ToList() (eller ToArray(), ToDictionary()) när du vill ha ett fast resultat.
Snabbreferens
| Metod | Vad den gör |
|---|---|
Where(x => ...) | Filtrera — behåll de som matchar |
Select(x => ...) | Transformera — ny form på varje element |
OrderBy / OrderByDescending | Sortera |
GroupBy(x => ...) | Gruppera i nycklar |
First / Load / Single | Hämta ett element (kastar om inte hittat) |
FirstOrDefault | Hämta ett element eller default |
Any / All | Finns något / gäller det alla? |
Count / Sum / Max / Min / Average | Aggregera |
Take(n) / Skip(n) | Paginering |
Distinct() | Ta bort dubbletter |
ToList() | Materialisera resultatet |
Join — koppla ihop samlingar
Join kombinerar två samlingar baserat på en gemensam nyckel, precis som ett INNER JOIN i SQL. I stället för att returnera ett anonymt objekt kan du nu få ett tupel direkt:
var orders = new List<(int CustomerId, string Product)>{ (1, "Laptop"), (2, "Mus"), (1, "Tangentbord")};
var customers = new List<(int Id, string Name)>{ (1, "Anna"), (2, "Björn"), (3, "Clara")};
// Join returnerar tupel direktvar result = customers.Join(orders, customer => customer.Id, order => order.CustomerId);
foreach (var (customer, order) in result) Console.WriteLine($"{customer.Name}: {order.Product}");Output
Anna: LaptopAnna: TangentbordBjörn: MusClara är inte med — INNER JOIN returnerar bara matchande rader.
FullJoin — alla rader från båda samlingar
FullJoin returnerar alla element från båda samlingar. Saknar ett element en matchning på den andra sidan, får det default i stället:
var left = new List<(int Id, string Name)> { (1, "Anna"), (2, "Björn"), (3, "Clara") };var right = new List<(int Id, string City)> { (2, "Göteborg"), (3, "Stockholm"), (4, "Malmö") };
var full = left.FullJoin(right, l => l.Id, r => r.Id);
foreach (var (l, r) in full){ var name = l.Name ?? "(ingen)"; var city = r.City ?? "(ingen stad)"; Console.WriteLine($"{l.Id}: {name} — {city}");}Output
1: Anna — (ingen stad)2: Björn — Göteborg3: Clara — Stockholm4: (ingen) — Malmö| Join-typ | Returnerar |
|---|---|
Join | Bara matchande rader (INNER JOIN) |
FullJoin | Alla rader från båda sidor, oavsett matchning |
GroupJoin | Vänster sida med en grupp av matchande rader från höger |
TL;DR
LINQ = deklarativt arbete med samlingar. Where filtrerar, Select transformerar, OrderBy sorterar, aggregatmetoderna räknar ihop. Kedja metoderna för läsbar, kompakt kod. Kom ihåg ToList() när du vill ha ett fast resultat.