7. díl - LINQ v C# - revoluce v dotazování

C# .NET Kolekce a LINQ LINQ v C# - revoluce v dotazování

LINQ označuje soubor nástrojů pro dotazování se na data. Jedná se o velmi revoluční technologii, která práci s jakýmikoli daty zjednodušuje a zobecňuje.

Motivace

Určitě jsme všichni doteď pracovali s různými typy kolekcí různým způsobem. Jinak jsme hledali prvek v poli, jinak jsme četli data z XML souboru a jinak bychom hledali uživatele v databázi. Představte si ale, kdyby existoval jeden unifikovaný způsob, jakým se na data dotazovat. Kdybychom mohli ten samý dotaz spustit jak na obyčejném poli, tak na XML souboru nebo databázi. Asi tušíte, že LINQ nám poskytuje přesně takový komfort. Jedná se o obrovskou abstrakci, která je vykoupena pouze zanedbatelným snížením výkonu a která vyhnala programování v C# do nových výšin.

LINQ jako jazyk

LINQ je poměrně sofistikovaná a rozsáhlá technologie. Její název pochází z anglického Language INtegrated Query. Jak název napovídá, jedná se o dotazovací jazyk, který je integrovaný přímo do syntaxe jazyka C#. Je tedy jeho součástí a to od C# 3.0 a .NET frameworku 3.5. Od novějších verzí běží dokonce na více vláknech, což zvyšuje efektivitu této technologie.

LINQ je velmi podobný jazyku SQL a je to tedy jazyk deklarativní. Programu sdělíme co hledáme a už nás moc nezajímá, jakým způsobem pro nás data opravdu vyhledá. Výhodou integrace LINQ do C# je syntaktická kontrola dotazů při překladu programu.

Udělejme si malý příklad, než půjdeme dál. Založte si nový projekt, půjde o konzolovou aplikaci se jménem LINQ. Vytvoříme si jednoduché pole textových řetězců.

string[] jmena = {"David", "Martin", "Dan", "Petr", "Vratislav", "Eliska"};

Nyní si pomocí LINQ dotazu z tohoto pole vybereme ty položky, jejichž délka je větší než 5 písmen. Do programu zapište následující kód:

var dotaz = from j in jmena
            where (j.Length > 5)
            select j;

Dotaz nápadně připomíná SQL, ti kteří ho znají mají výhodu. Myslím, že SQL nad polem jste ještě nevolali, že? :) Hned si dotaz podrobně popíšeme, nejprve ale dokončeme náš program a to tím, že si výsledek dotazu vypíšeme do konzole:

// výpis výsledku
foreach (string jmeno in dotaz)
{
        Console.WriteLine(jmeno);
}
Console.ReadKey();

Výstup programu:

Ukázka použití LINQ dotazu v C# .NET

Jak vypadá dotaz

Vraťme se k našemu dotazu, který vypadal takto:

var dotaz = from j in jmena
            where (j.Length > 5)
            select j;

Znalci SQL budou jistě překvapeni, že je dotaz pozpátku. Má to své opodstatnění, ke kterému dojdeme.

Nejprve určujeme odkud budeme data vybírat, slouží k tomu klíčové slovo from. Za from následuje proměnná, která bude ve zbytku dotazu reprezentovat prvek z kolekce. Dále následuje klíčové slovo in a samotná kolekce. Je to podobné jako u cyklu foreach. Dotazy se píší na několik řádků, aby byly přehlednější. To oceníte zejména u těch složitějších.

Pro opodmínkování můžeme uvést řádek s klíčovým slovem where, za ním následuje podmínka. Podmínky v tomto případě píšeme úplně stejně, jako jsme to dělali doposud.

Na posledním řádku následuje klíčové slovo select, pomocí kterého určíme co vybíráme. Zde vybíráme celý prvek z kolekce, tedy j. Stejně tak bychom ale mohli vybrat třeba jen jeho délku j.Length nebo cokoli jiného.

Dotaz ukládáme do proměnné typu var, s tímto typem jsme se ještě nesetkali a vlastně to ani datový typ není. Klíčové slovo var nám umožňuje přenechat výběr datového typu na kompileru (rozumějte, že ho za nás přiřadí C# sám při překladu). Teoreticky bychom var mohli použít i jindy, např. takto:

var s = "C# pozná že toto je string a dá proměnné s typ string";
var i = 10;

Kód výše C# přeloží v podstatě na toto:

string s = "C# pozná že toto je string a dá proměnné s typ string";
int i = 10;

Var tedy umožňuje určit datový typ až při překladu programu a vlastně nás od datového typu odstiňuje. V běžných programech by bylo var naobtíž, jelikož specifikace typů má svůj smysl. Typy tedy budeme psát dále a v žádném případě je nenahrazujte slovem var, jak se to někteří začátečníci zcela chybně naučí.

Var bylo zavedeno kvůli LINQ a to ze třech důvodů. Zaprvé jsou datové typy dotazů pomerně složité a bylo by komplikované je vždy explicitně specifikovat. Zadruhé když změníme typ kolekce, změní se i typ dotazu, což by vyžadovalo zbytečnou editaci kódu a snížilo obecnost technologie. Zatřetí s LINQem přichází tzv. anonymní typy, u kterých se bez var neobejdeme, brzy se k nim dostaneme. Co si pamatujte je, že var má své místo pouze v dotazech a v běžném kódu nemá co dělat, i když by se tam teoreticky dalo použít.

Další častou chybou je, že si lidé myslí, že var deklaruje proměnnou dynamického typu, tedy že do ní můžeme uložit co chceme. Není tomu tak, typ se napevno určí při překladu a během programu ho nelze měnit. Kód níže tedy nebude fungovat:

// tento kód nebude fungovat
var promenna = "Teď tam je text";
promenna = 10; // Teď tam je číslo

Program výše vytvoří proměnnou typu string a poté upadne, protože se do stringu snažíme uložit int.

Pod pokličkou

Jak že to celé funguje? Když se podíváte na začátek vašeho zdrojového kódu, uvidíte, že obsahuje následující using:

using System.Linq;

Ten je výchozí u všech typů projektů. Zkusme ho zakomentovat, v tu chvíli nám Visual Studio podtrhne v dotazu proměnnou jmena.

LINQ funguje pomocí tzv. providerů, těch je několik typů a je i možno si definovat vlastní. My nyní používáme LINQ To Objects, který je právě ve jmenném prostoru System.Linq a který rozšíří obyčejné kolekce jako jsou např. pole a listy o další metody navíc. Pod pokličkou jsou tedy rozšiřující metody.

Zkusme si nyní (ještě se zakomentovaným usingem) vyvolat nabídku metod na našem poli. Napišme jmena. (jmena a tečku)., abychom vyvolali seznam metod na poli:

Obyčejné metody na poli v C# .NET

Nyní řádek opět odkomentujme a udělejme to samé znovu:

Linq metody na poli v C# .NET

Na obyčejném poli máme najednou kvantum nových metod. Když C# vykonává LINQ dotaz, volá na pozadí na kolekci tyto metody. Ty jsou řešené přes nám již známé lambda výrazy.

Náš dotaz:

var dotaz = from j in jmena
            where (j.Length > 5)
            select j;

tedy C# přežvýká a vygeneruje následující kód:

var dotaz = jmena.Where(j => j.Length > 5).Select(j => j);

Můžete si vyzkoušet, že dotaz bude fungovat stejně. Máme možnost s LINQ pracovat i takto, ale pomocí SQL-like zápisu je to mnohem stravitelnější. Mimochodem, právě jsme si vysvětlili, proč je v dotazu nejprve where a až poté select. Data se musí nejprve najít metodou Where() a z výsledku se teprve poté označí co nás zajímá metodou Select(). Důvodem je tedy posloupnost metod pod pokličkou technologie.

Na závěr si prozraďme, na co se v našem případě přeloží onen záhadný typ var. Výsledný typ dotazu je:

System.Linq.Enumerable.WhereArrayIterator<string>

Jelikož nemůžeme z hlavy vědět jaký typ LINQ zrovna vrátí (přesněji řečeno bychom od toho měli být odstíněni), byl zaveden typ var, jak již bylo řečeno výše.

Příště budeme pokračovat v dotazování.


 

Stáhnout

Staženo 392x (23.17 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (9 hlasů) :
4.777784.777784.777784.777784.77778


 


Miniatura
Předchozí článek
Fronta a zásobník v C# .NET
Miniatura
Všechny články v sekci
Kolekce v C# .NET a LINQ

 

 

Komentáře
Zobrazit starší komentáře (2)

Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

http://msdn.microsoft.com/…b384061.aspx

"However, the use of var does have at least the potential to make your code more difficult to understand for other developers. For that reason, the C# documentation generally uses var only when it is required."

Dokud nevyjde konvence, že se má var používat všude, je jeho kombinace s běžnými typy matoucí.

Odpovědět 9.2.2013 13:44
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

LINQ je vždy pomalejší než klasický přístup.

Odpovědět  -1 9.2.2013 13:44
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Odpovídá na David Čápka
Luboš Běhounek (Satik):

http://msdn.microsoft.com/…f926074.aspx

"Use implicit typing for local variables when the type of the variable is obvious from the right side of the assignment, or when the precise type is not important."

Odpovědět  +1 10.2.2013 10:25
:)
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Luboš Běhounek (Satik)
David Čápka:

To je blbost, var se má používat právě když typ není zřejmý, sám jsi to říkal mimochodem, že ho v těchto případech používáš. Protiřečí si tedy i MSDN, další ukázka toho, jaký to dělá bordel a proč by se s tím mělo šetřit.

Odpovědět  -1 10.2.2013 10:32
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
lcet.m
Člen
Avatar
lcet.m:

Víte co kluci? Já vám k tomu neřeknu vůbec nic :D

(Váš Varvšudekdetojde)

 
Odpovědět 10.2.2013 10:56
Avatar
nro
Člen
Avatar
nro:

Jeste ze ti chlapci z vyvojoveho tymu od FoxPro presli do Netu, aby vymysleli Linq jinak by byl Net s databazemi v riti :-)

Krasne jsem si kdysi pokecal s sefem tymu, jehoz tym ma na starosi Linq. Borci na spravnem miste a chvala za ne.

 
Odpovědět 9.11.2013 23:43
Avatar
xxx
Člen
Avatar
Odpovídá na David Čápka
xxx:

jj var sa pouziva ked datovy typ nie je zrejmy, hovori sa tomu aj mechanizmus typovej inferencie. Ale zaujimave pre mna je ze pises ze mame pouzivat var len v dotazoch a nie v beznom kode, lebo mna na vyske ucili vytvarat aj anonymne triedy pomocou var.... tak som to nepovazovala za zle...
inak pekny tutorial :)

Odpovědět 27.4.2014 12:08
kto chce hlada sposoby, kto nechce hlada dovody...
Avatar
VitekST
Člen
Avatar
VitekST:

No ajaj! A já jsem var používal všude....

 
Odpovědět 3.8.2015 17:04
Avatar
forcabarca
Člen
Avatar
forcabarca:

V

Editováno 7. ledna 20:02
 
Odpovědět 7. ledna 19:59
Avatar
Jakub Šárník:

Menší upřesnění teď: var se i podle MS může používat klidně i tam, kde je naprosto zřejmý typ z pravé strany přiřazení. Microsoft sám to tak taky už používá.

 
Odpovědět 9. ledna 11:13
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 12. Zobrazit vše