LINQ (Language Integrated Query) je technologie integrovaná v .NET, která umožňuje dotazovat se na data přímo v kódu, ať už se jedná o kolekce v paměti, databáze, XML dokumenty nebo jiné datové zdroje. Jejím hlavním cílem je sjednotit způsob práce s daty bez ohledu na jejich zdroj, aby nebylo nutné učit se specifické dotazovací jazyky pro různé typy úložišť. Díky LINQ lze data filtrovat, řadit, transformovat nebo seskupovat jednoduchým, čitelným a typově bezpečným způsobem.

Vyhodnocování LINQ

LINQ operace mohou být vyhodnocovány dvěma způsoby:

  • Okamžité vyhodnocení (Immediate Execution) Výsledek dotazu se vyhodnotí a uloží ihned, například při použití metod jako ToList(), ToArray() nebo Count(). Data se ihned načtou a zpracují.
  • Odložené vyhodnocení (Deferred Execution) Dotaz se neprovádí okamžitě, ale až při potřebě získat výsledek (např. v foreach). To umožňuje kombinovat více dotazů bez mezivýsledků a provést vše najednou. Odložené vyhodnocení šetří paměť a umožňuje efektivnější práci s daty, ale může vést ke změnám výsledků, pokud se zdrojová data před vyhodnocením změní.

Lambda funkce (Anonymní funkce)

  • Lambda funkce je krátká anonymní funkce (anonymní = není pojmenovaná), která může mít parametry a tělo.
  • Je to zkrácený zápis delegátů (funkcí nebo metod předaných jako parametr).
  • Typicky se používá ve spojení s LINQ nebo u událostí, callbacků či filtrů.
  • Syntaxe: (parametry) => výraz
    • Př.: Jednoduchý příklad: x => x * x
    • Př.: Příklad s blokem příkazů: (x, y) => { return x + y; }

Ukázky

Filtrace kolekce:

var adults = people.Where(p => p.Age >= 18);

Sečtení dvou čísel:

Func<int, int, int> add = (a, b) => a + b;
int result = add(5, 7); // result = 12

Lambda bez parametrů:

Action greet = () => Console.WriteLine("Hello!");
greet();

Základní funkce a jejich použití

LINQ poskytuje mnoho standardních metod, které se nazývají operátory dotazů. Mezi nejpoužívanější patří:

Where – filtruje prvky podle podmínky

var adults = people.Where(p => p.Age >= 18);

Select – transformuje prvky do jiné podoby

var names = people.Select(p => p.Name);

OrderBy / OrderByDescending – řadí prvky

var ordered = people.OrderBy(p => p.Name);

GroupBy – seskupuje prvky podle klíče

var groups = people.GroupBy(p => p.City);

First / FirstOrDefault – získá první prvek (nebo výchozí hodnotu)

var firstAdult = people.FirstOrDefault(p => p.Age >= 18);

Any / All – ověřuje, zda některé nebo všechny prvky splňují podmínku

bool anyMinors = people.Any(p => p.Age < 18);

Count – spočítá prvky

int countAdults = people.Count(p => p.Age >= 18);

Fluent API

V C# se LINQ nejčastěji zapisuje pomocí tzv. Fluent API, kde se jednotlivé metody řetězí za sebe. Tato forma zápisu je přehledná, dobře čitelná a umožňuje snadno vytvářet složité dotazy. FluentAPI není specifické pouze pro jazyk C#, ale lze jej nalézt v mnoha moderních programovacích jazycích

Příklad

Dotaz na všechny osoby starší 18 let seřazené podle jména vzestupně:

var result = people
    .Where(p => p.Age >= 18)
    .OrderBy(p => p.Name)
    .Select(p => new { p.Name, p.Age });

Alternativou Fluent API je dotazovací syntaxe (query syntax), která připomíná SQL:

var result = from p in people
             where p.Age >= 18
             orderby p.Name
             select new { p.Name, p.Age };

Anonymní objekty

Stejně jako existují anonymní funkce, tak C# podporuje i tvorbu anonymních objektů. Tvoří se tak, že se neuvede datový typ

var person = new
{
    Name = "Pepa",
    Age = 38
};

Použití anonymních objektů je vhodné jen pokud se jedná o dočasné objekty. Jejich využitím ztrácíme typovou kontrolu a vlastnosti jako například zapouzdření, které nabízí silně typované třídy.