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
-
base
pří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
-
dynamic
operace -
Operátory sjednocení s
null
levou stranou nebodefault
literá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
-
throw
výrazy - Přístup k
static virtual
nebo 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 (..
) -
async
výrazy lambda neboawait
výrazy, včetněawait foreach
aawait using
-
N-ticové literály, převody n-tic, n-ticové
==
nebo!=
, nebowith
výrazy -
Zahodí (
_
), dekonstrukce přiřazení, operátor pro porovnáváníis
vzorů nebo výraz pro porovnáváníswitch
vzorů. - Volání COM s vynechanými
ref
argumenty -
ref
,in
neboout
parametry,ref
návratové hodnoty,out
argumenty nebo jakékoli hodnoty typuref struct