Sdílet prostřednictvím


Stromy výrazů

Stromy výrazů představují kód ve stromové datové struktuře, kde každý uzel je výraz, například volání metody nebo binární operace, například x < y.

Pokud jste použili LINQ, máte zkušenosti s bohatou knihovnou, ve které Func typy jsou částí sady API. (Pokud jazyk LINQ neznáte, pravděpodobně si budete chtít přečíst kurz LINQ a článek o výrazech lambda před tímto výrazem .) Stromy výrazů poskytují bohatší interakci s argumenty, které jsou funkcemi.

Při vytváření dotazů LINQ píšete argumenty funkce, obvykle pomocí výrazů lambda. V typickém dotazu LINQ se tyto argumenty funkce transformují na delegáta, který kompilátor vytvoří.

Už píšete kód, který používá stromy výrazů. LINQ API v rámci Entity Frameworku přijímají stromy výrazů jako argumenty pro vzorce dotazů LINQ. Díky tomu může Entity Framework přeložit dotaz, který jste napsali v jazyce C# do SQL, který se spustí v databázovém stroji. Dalším příkladem je Moq, což je oblíbený framework pro vytváření mocků v .NET.

Pokud chcete mít bohatší interakci, musíte použít stromy výrazů. Stromy výrazů představují kód jako strukturu, kterou prozkoumáte, upravíte nebo spustíte. Tyto nástroje umožňují manipulovat s kódem během běhu. Napíšete kód, který zkoumá spuštěné algoritmy nebo vloží nové funkce. V pokročilejších scénářích upravíte spuštěné algoritmy a dokonce přeložíte výrazy jazyka C# do jiného formuláře pro provádění v jiném prostředí.

Zkompilujete a spustíte kód reprezentovaný stromy výrazů. Vytváření a spouštění stromů výrazů umožňuje dynamickou úpravu spustitelného kódu, spouštění dotazů LINQ v různých databázích a vytváření dynamických dotazů. Další informace o stromech výrazů v LINQ naleznete v tématu Použití stromů výrazů k vytváření dynamických dotazů.

Stromy výrazů se také používají v modulu runtime dynamického jazyka (DLR) k zajištění interoperability mezi dynamickými jazyky a rozhraním .NET a k umožnění autorům kompilátorů vyprodukovat stromy výrazů namísto jazyka Microsoft intermediate language (CIL). Další informace o DLR najdete v části Přehled modulu dynamického jazykového runtime.

Můžete mít kompilátor jazyka C# nebo Visual Basic, který vám vytvoří strom výrazů na základě anonymního výrazu lambda, nebo stromy výrazů můžete vytvořit ručně pomocí System.Linq.Expressions oboru názvů.

Pokud je výraz lambda přiřazen k proměnné typu Expression<TDelegate>, kompilátor generuje kód pro sestavení stromu výrazu, který představuje výraz lambda.

Následující příklady kódu ukazují, jak přimět kompilátor jazyka C#, aby vytvořil výrazový strom, který představuje lambda výraz num => num < 5.

Expression<Func<int, bool>> lambda = num => num < 5;

Stromy výrazů vytvoříte v kódu. Strom vytvoříte tak, že vytvoříte každý uzel a připojíte je do stromové struktury. Naučíte se vytvářet výrazy v článku o vytváření stromů výrazů.

Stromy výrazů jsou neměnné. Pokud chcete změnit strom výrazů, musíte vytvořit nový strom výrazu zkopírováním existujícího stromu a nahrazením uzlů v něm. Návštěvník stromu výrazů slouží k procházení existujícího stromu výrazů. Další informace najdete v článku o překladu stromů výrazů.

Jakmile vytvoříte strom výrazu, spustíte kód reprezentovaný stromem výrazu.

Omezení

Kompilátor jazyka C# generuje stromy výrazů pouze z výrazů lambda (nebo jednořádkových lambda). Nedokáže analyzovat lambda výrazy (nebo víceřádkové lambda výrazy). Další informace o výrazech lambda v jazyce C# najdete v tématu Výrazy lambda.

Existují některé novější prvky jazyka C#, které se dobře nepřekládají do stromů výrazů. Stromy výrazů nemohou obsahovat await výrazy ani async výrazy lambda. Mnoho funkcí přidaných v jazyce C# 6 a novějších se nezobrazuje přesně tak, jak je napsané ve stromech výrazů. Místo toho jsou novější funkce zpřístupněny ve stromech výrazů v ekvivalentní, dřívější syntaxi, pokud je to možné. Jiné konstrukce nejsou k dispozici. Znamená to, že kód, který interpretuje stromy výrazů, funguje stejně při zavedení nových jazykových funkcí. I s těmito omezeními ale stromy výrazů umožňují vytvářet dynamické algoritmy, které spoléhají na interpretaci a úpravu kódu, který je reprezentován jako datová struktura. Umožňuje pokročilým knihovnám, jako je Entity Framework, dosáhnout jejich cílů.

Stromy výrazů nepodporují nové typy uzlů výrazů. Jedná se o zásadní změnu pro všechny knihovny, které interpretují stromy výrazů, aby zavedly nové typy uzlů. Následující seznam obsahuje většinu jazykových prvků jazyka C#, které se nedají použít: