Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
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:
- Podmíněné metody odebrané z výstupu
-
basepřístup - Výrazy skupiny metod, včetně referenci na (
&) skupinu metod a výrazy anonymních metod. - Odkazy na místní funkce
- Příkazy, včetně výrazů přiřazení (
=) a výrazů s tělem příkazů - Částečné metody pouze s definující deklarací
- Nebezpečné operace ukazatele
-
dynamicoperace -
Operátory sjednocení s
nulllevou stranou nebodefaultliterálem, přiřazením nulového sjednocení a operátorem šíření hodnoty null (?.) - Inicializátory vícerozměrného pole, indexované vlastnosti a inicializátory slovníku
- kolekční výrazy
-
throwvýrazy - Přístup k
static virtualnebo kabstractčlenům rozhraní - Výrazy lambda s atributy
- Interpolované řetězce
- Převody řetězců UTF-8 nebo řetězcové literály UTF-8
- Vyvolání metody pomocí argumentů proměnných, pojmenovaných argumentů nebo volitelných argumentů
- Výrazy používající System.Index nebo System.Range, index "from end" (
^) – operátor nebo výrazy rozsahu (..) -
asyncvýrazy lambda neboawaitvýrazy, včetněawait foreachaawait using -
N-ticové literály, převody n-tic, n-ticové
==nebo!=, nebowithvýrazy -
Zahodí (
_), dekonstrukce přiřazení, operátor pro porovnáváníisvzorů nebo výraz pro porovnáváníswitchvzorů. - Volání COM s vynechanými
refargumenty -
ref,innebooutparametry,refnávratové hodnoty,outargumenty nebo jakékoli hodnoty typuref struct