Vztahy typů v operacích dotazu LINQ (C#)
Pokud chcete efektivně psát dotazy, měli byste porozumět tomu, jak typy proměnných v celé operaci dotazu vzájemně souvisejí. Pokud těmto relacím rozumíte, snadněji pochopíte ukázky LINQ a příklady kódu v dokumentaci. Dále pochopíte, co se stane, když jsou proměnné implicitně zadány pomocí .var
Operace dotazů LINQ jsou silně zadané ve zdroji dat, v samotném dotazu a při provádění dotazu. Typ proměnných v dotazu musí být kompatibilní s typem prvků ve zdroji dat a s typem proměnné iterace v foreach
příkazu. Tento silný typ zaručuje, že chyby typu jsou zachyceny v době kompilace, když je lze opravit, než se na ně uživatelé dostanou.
Aby bylo možné tyto relace typů předvést, většina příkladů, které následují, používají explicitní psaní pro všechny proměnné. Poslední příklad ukazuje, jak stejné principy platí i při použití implicitního psaní pomocí var
.
Dotazy, které transformují zdrojová data
Následující obrázek znázorňuje operaci dotazu LINQ to Objects, která neprovádí žádné transformace dat. Zdroj obsahuje posloupnost řetězců a výstup dotazu je také posloupnost řetězců.
- Argument typu zdroje dat určuje typ proměnné rozsahu.
- Typ vybraného objektu určuje typ proměnné dotazu. Tady
name
je řetězec. Proto je proměnná dotazu .IEnumerable<string>
- Proměnná dotazu se v
foreach
příkazu iteuje. Vzhledem k tomu, že proměnná dotazu je posloupnost řetězců, je proměnná iterace také řetězec.
Dotazy, které transformují zdrojová data
Následující obrázek znázorňuje operaci dotazu LINQ to SQL, která provádí jednoduchou transformaci dat. Dotaz přebírá posloupnost Customer
objektů jako vstup a vybere pouze Name
vlastnost ve výsledku. Protože Name
je řetězec, dotaz vytvoří posloupnost řetězců jako výstup.
- Argument typu zdroje dat určuje typ proměnné rozsahu.
- Příkaz
select
vrátíName
vlastnost místo kompletníhoCustomer
objektu. ProtožeName
je řetězec, typ argumentucustNameQuery
jestring
, nikoliCustomer
. - Vzhledem k tomu
custNameQuery
, že je posloupnost řetězců,foreach
musí být iterační proměnná smyčky také .string
Následující obrázek znázorňuje o něco složitější transformaci. Příkaz select
vrátí anonymní typ, který zachycuje pouze dva členy původního Customer
objektu.
- Argument typu zdroje dat je vždy typem proměnné rozsahu v dotazu.
- Protože příkaz
select
vytvoří anonymní typ, musí být proměnná dotazu implicitně zadána pomocí .var
- Vzhledem k tomu, že typ proměnné dotazu je implicitní, musí být implicitní i iterační proměnná ve
foreach
smyčce.
Umožňuje kompilátoru odvodit informace o typu.
I když byste měli porozumět relacím typů v operaci dotazu, máte možnost, aby kompilátor udělal všechno za vás. Klíčové slovo var lze použít pro libovolnou místní proměnnou v operaci dotazu. Následující obrázek je podobný příkladu čísla 2, který jsme probrali dříve. Kompilátor však poskytuje silný typ pro každou proměnnou v operaci dotazu.
LINQ a obecné typy (C#)
Dotazy LINQ jsou založené na obecných typech. Než začnete psát dotazy, nepotřebujete podrobné znalosti obecných typů. Možná ale budete chtít porozumět dvěma základním konceptům:
- Když vytvoříte instanci obecné třídy kolekce, například List<T>, nahradíte "T" typem objektů, které bude seznam obsahovat. Například seznam řetězců je vyjádřen jako
List<string>
a seznamCustomer
objektů je vyjádřen jakoList<Customer>
. Obecný seznam je silného typu a poskytuje mnoho výhod oproti kolekcí, které ukládají jejich prvky jako Object. Pokud se pokusíte přidat do objektuCustomer
List<string>
, zobrazí se chyba v době kompilace. Je snadné používat obecné kolekce, protože nemusíte provádět přetypování typu za běhu. - IEnumerable<T> je rozhraní, které umožňuje výčet obecných tříd kolekcí pomocí
foreach
příkazu. Obecné třídy kolekce podporují IEnumerable<T> stejně jako obecné třídy kolekce, jako ArrayList je podpora IEnumerable.
Další informace o obecných typů najdete v tématu Obecné typy.
Proměnné T> IEnumerable<v dotazech LINQ
Proměnné dotazu LINQ jsou zadány jako IEnumerable<T> nebo odvozený typ, například IQueryable<T>. Když uvidíte proměnnou dotazu, která je zadáváná jako IEnumerable<Customer>
, znamená to, že dotaz při jeho spuštění vytvoří sekvenci nulových nebo více Customer
objektů.
IEnumerable<Customer> customerQuery =
from cust in customers
where cust.City == "London"
select cust;
foreach (Customer customer in customerQuery)
{
Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}
Umožňuje kompilátoru zpracovávat deklarace obecného typu.
Pokud chcete, můžete se vyhnout obecné syntaxi pomocí klíčového slova var . Klíčové var
slovo dává kompilátoru pokyn, aby odvodil typ proměnné dotazu tak, že se podívá na zdroj dat zadaný v from
klauzuli. Následující příklad vytvoří stejný zkompilovaný kód jako předchozí příklad:
var customerQuery2 =
from cust in customers
where cust.City == "London"
select cust;
foreach(var customer in customerQuery2)
{
Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}
Klíčové var
slovo je užitečné, když je typ proměnné zřejmý nebo pokud není důležité explicitně zadat vnořené obecné typy, jako jsou ty, které jsou vytvářeny pomocí skupinových dotazů. Obecně doporučujeme, abyste pokud používáte var
, uvědomte si, že může váš kód ztížit čtení ostatních. Další informace naleznete v tématu Implicitně typované místní proměnné.