Výraz stromů (C# a Visual Basic)
Výraz stromy představují kód podobné stromu datové struktury, kde každý uzel je výraz, například, volání metody nebo binární operace jako x < y.
Lze kompilovat a spustit kód reprezentované výraz stromů.To umožňuje dynamické změny spustitelný kód spuštění LINQ dotazů v různých databází a vytváření dynamických dotazy.Další informace o výraz olivovníků LINQ viz Jak: použití výrazu stromy vytvářet dynamické dotazy (C# a Visual Basic) a Názorný postup: Vytváření poskytovatele IQueryable LINQ.
Výraz stromy používají také v dynamic language runtime (DLR) poskytovat interoperabilitu mezi dynamické jazyky a.NET Framework a Povolit kompilátor autoři k vyzařování výraz stromy namísto Microsoft zprostředkujících jazyk (MSIL).Zobrazit další informace o DLR Dynamický přehled Language Runtime.
Máte vytvořit ve stromu výraz založený na anonymní lambda výraz nebo výraz stromy lze vytvořit ručně pomocí kompilátoru C# nebo Visual Basic System.Linq.Expressions oboru názvů.
Vytvoření výrazu stromy z Lambda výrazů
Pokud je přiřazena proměnné typu lambda výraz Expression<TDelegate>, kompilátor vyzařuje kódu sestavení stromu výraz, který představuje lambda výraz.
C# a Visual Basic kompilátory lze generovat výraz stromy pouze z výrazu lambdas (nebo lambdas jeden řádek).Nelze analyzovat, příkaz lambdas (nebo lambdas na více řádků).Další informace o lambda výrazy v jazyce C# Lambda výrazy (Příručka programování C#); Visual Basic naleznete v Lambda výrazy (Visual Basic).
Kód následující příklady ukazují, jak jste C# a Visual Basic kompilátory vytvoření stromu výraz, který představuje lambda výraz num => num < 5 (C#) nebo Function(num) num < 5 (Visual Basic).
Dim lambda As Expression(Of Func(Of Integer, Boolean)) =
Function(num) num < 5
Expression<Func<int, bool>> lambda = num => num < 5;
Vytvoření výrazu stromů pomocí rozhraní API
Vytvořit výraz stromů pomocí rozhraní API Expression třídy.Tato třída obsahuje statické výrobních metod, které uzly stromu specifických typů, například vytvořit výraz ParameterExpression, která představuje proměnnou nebo parametr, nebo MethodCallExpression, která představuje volání metody.ParameterExpression, MethodCallExpression, a další výraz specifické typy jsou rovněž definovány v System.Linq.Expressions oboru názvů.Tyto typy odvodit z abstraktní typ Expression.
Následující příklad kódu ukazuje, jak vytvořit strom výraz, který představuje lambda výraz num => num < 5 (C#) nebo Function(num) num < 5 (Visual Basic) pomocí rozhraní API.
' Import the following namespace to your project: System.Linq.Expressions
' Manually build the expression tree for the lambda expression num => num < 5.
Dim numParam As ParameterExpression = Expression.Parameter(GetType(Integer), "num")
Dim five As ConstantExpression = Expression.Constant(5, GetType(Integer))
Dim numLessThanFive As BinaryExpression = Expression.LessThan(numParam, five)
Dim lambda1 As Expression(Of Func(Of Integer, Boolean)) =
Expression.Lambda(Of Func(Of Integer, Boolean))(
numLessThanFive,
New ParameterExpression() {numParam})
// Add the following using directive to your code file:
// using System.Linq.Expressions;
// Manually build the expression tree for
// the lambda expression num => num < 5.
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expression<Func<int, bool>> lambda1 =
Expression.Lambda<Func<int, bool>>(
numLessThanFive,
new ParameterExpression[] { numParam });
V.NET Framework 4, rozhraní API výraz stromy také podporuje přiřazení a řízení toku výrazy například smyčky podmíněné bloky a try-catch bloky.Pomocí rozhraní API můžete vytvořit výraz stromů, které jsou složitější než ty, které mohou být vytvořeny z lambda výrazy kompilátorů C# a Visual Basic.Následující příklad ukazuje způsob vytvoření stromu výraz, který vypočítá faktoriál zadaného čísla.
' Creating a parameter expression.
Dim value As ParameterExpression =
Expression.Parameter(GetType(Integer), "value")
' Creating an expression to hold a local variable.
Dim result As ParameterExpression =
Expression.Parameter(GetType(Integer), "result")
' Creating a label to jump to from a loop.
Dim label As LabelTarget = Expression.Label(GetType(Integer))
' Creating a method body.
Dim block As BlockExpression = Expression.Block(
New ParameterExpression() {result},
Expression.Assign(result, Expression.Constant(1)),
Expression.Loop(
Expression.IfThenElse(
Expression.GreaterThan(value, Expression.Constant(1)),
Expression.MultiplyAssign(result,
Expression.PostDecrementAssign(value)),
Expression.Break(label, result)
),
label
)
)
' Compile an expression tree and return a delegate.
Dim factorial As Integer =
Expression.Lambda(Of Func(Of Integer, Integer))(block, value).Compile()(5)
Console.WriteLine(factorial)
' Prints 120.
// Creating a parameter expression.
ParameterExpression value = Expression.Parameter(typeof(int), "value");
// Creating an expression to hold a local variable.
ParameterExpression result = Expression.Parameter(typeof(int), "result");
// Creating a label to jump to from a loop.
LabelTarget label = Expression.Label(typeof(int));
// Creating a method body.
BlockExpression block = Expression.Block(
// Adding a local variable.
new[] { result },
// Assigning a constant to a local variable: result = 1
Expression.Assign(result, Expression.Constant(1)),
// Adding a loop.
Expression.Loop(
// Adding a conditional block into the loop.
Expression.IfThenElse(
// Condition: value > 1
Expression.GreaterThan(value, Expression.Constant(1)),
// If true: result *= value --
Expression.MultiplyAssign(result,
Expression.PostDecrementAssign(value)),
// If false, exit the loop and go to the label.
Expression.Break(label, result)
),
// Label to jump to.
label
)
);
// Compile and execute an expression tree.
int factorial = Expression.Lambda<Func<int, int>>(block, value).Compile()(5);
Console.WriteLine(factorial);
// Prints 120.
Další informace naleznete v Generování dynamického metody s výraz stromy v roce 2010 Visual Studio.
Analýza výraz stromy
Následující příklad kódu ukazuje, jak výraz strom, který představuje lambda výraz num => num < 5 (C#) nebo Function(num) num < 5 (Visual Basic) lze rozložit na jeho části.
' Import the following namespace to your project: System.Linq.Expressions
' Create an expression tree.
Dim exprTree As Expression(Of Func(Of Integer, Boolean)) = Function(num) num < 5
' Decompose the expression tree.
Dim param As ParameterExpression = exprTree.Parameters(0)
Dim operation As BinaryExpression = exprTree.Body
Dim left As ParameterExpression = operation.Left
Dim right As ConstantExpression = operation.Right
Console.WriteLine(String.Format("Decomposed expression: {0} => {1} {2} {3}",
param.Name, left.Name, operation.NodeType, right.Value))
' This code produces the following output:
'
' Decomposed expression: num => num LessThan 5
// Add the following using directive to your code file:
// using System.Linq.Expressions;
// Create an expression tree.
Expression<Func<int, bool>> exprTree = num => num < 5;
// Decompose the expression tree.
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
param.Name, left.Name, operation.NodeType, right.Value);
// This code produces the following output:
// Decomposed expression: num => num LessThan 5
Immutability výraz stromy
Výraz stromy by měly být neměnná.To znamená, že pokud chcete upravit ve stromu výraz, musí sestavit nového stromu výraz zkopírováním existující a uzly v jeho nahrazení.Můžete procházet existujícího stromu výraz návštěvník stromu výraz.Další informace naleznete v tématu Jak: Upravit výraz stromů (C# a Visual Basic).
Sestavování výrazu stromy
Expression<TDelegate> Typu Compile metoda, která je reprezentována ve stromu výraz do spustitelného delegát kód zkompiluje.
Následující příklad kódu ukazuje, jak ve stromu výraz sestavit a spustit výsledný kód.
' Creating an expression tree.
Dim expr As Expression(Of Func(Of Integer, Boolean)) =
Function(num) num < 5
' Compiling the expression tree into a delegate.
Dim result As Func(Of Integer, Boolean) = expr.Compile()
' Invoking the delegate and writing the result to the console.
Console.WriteLine(result(4))
' Prints True.
' You can also use simplified syntax
' to compile and run an expression tree.
' The following line can replace two previous statements.
Console.WriteLine(expr.Compile()(4))
' Also prints True.
// Creating an expression tree.
Expression<Func<int, bool>> expr = num => num < 5;
// Compiling the expression tree into a delegate.
Func<int, bool> result = expr.Compile();
// Invoking the delegate and writing the result to the console.
Console.WriteLine(result(4));
// Prints True.
// You can also use simplified syntax
// to compile and run an expression tree.
// The following line can replace two previous statements.
Console.WriteLine(expr.Compile()(4));
// Also prints True.
Další informace naleznete v tématu Jak: spustit výraz stromů (C# a Visual Basic).
Viz také
Úkoly
Jak: spustit výraz stromů (C# a Visual Basic)
Jak: Upravit výraz stromů (C# a Visual Basic)
Referenční dokumentace
Lambda výrazy (Příručka programování C#)
Koncepty
Dynamický přehled Language Runtime
Další zdroje
dynamické metody s výrazem stromy v roce 2010 Visual Studio generování