Sdílet prostřednictvím


Stromy výrazů (C# a Visual Basic)

Stromy výrazů představují kódu v operaci binární, volání metody nebo podobné stromu datové struktury, kde každý uzel je ve výrazu, například jako x < y.

Je možné zkompilovat a spouštět kód reprezentována stromy výrazů.To umožňuje dynamické úpravu spustitelného kódu, provádění dotazů LINQ dotazy v různých databází a vytváření dynamického dotazů.Další informace o stromy výrazů v technologii LINQ, naleznete v části Postupy: Použití stromů výrazů k sestavování dynamických dotazů (C# a Visual Basic).

Stromy výrazů používají také v dynamické language runtime (DLR) k zajištění kompatibility mezi dynamických jazyků a rozhraní .NET Framework a umožňuje autorům kompilátoru vydávání stromy výrazů namísto mezilehlá (MSIL Microsoft language).Další informace o DLR, naleznete v části Přehled DLR (Dynamic Language Runtime).

Máte vytvořit strom výrazu pro podle výrazu lambda anonymní, nebo můžete vytvořit stromy výrazů ručně pomocí kompilátoru jazyka C# nebo Visual Basic System.Linq.Expressions oboru názvů.

Vytváření stromy výrazů z Lambda výrazy

Kdy je přiřazena proměnné typu výrazu lambda Expression, kompilátor vydává kód k vytvoření strom výrazu, který představuje výrazu lambda.

C# a kompilátoru jazyka Visual Basic, můžete vygenerovat stromy výrazů pouze z lambda výrazy (nebo lambda výrazy jeden řádek).Nelze analyzovat, lambda (nebo víceřádkové lambda výrazy).Další informace o lambda výrazy v jazyce C#, naleznete v části Výrazy Lambda (Průvodce programováním v C#); Visual Basic, naleznete v části Lambda – výrazy (Visual Basic).

Následující příklady kódu ukazují, jak mají C# a Visual Basic kompilátoru vytvořit strom výrazu, který představuje výrazu lambda 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;

Vytváření stromy výrazů pomocí rozhraní API

Chcete-li vytvořit stromy výrazů pomocí rozhraní API, použijte Expression třídy.Tato třída obsahuje metody statické objekt pro vytváření, které vytvářejí výraz uzly stromu určitých typů, například ParameterExpression, která představuje proměnnou nebo parametr, nebo MethodCallExpression, která reprezentuje volání metody.ParameterExpression, MethodCallExpression, a dalších typů specifické pro výraz je definována v System.Linq.Expressions oboru názvů.Tyto typy jsou odvozeny od abstraktního typu Expression.

Následující příklad kódu ukazuje, jak vytvořit strom výrazu, který představuje výrazu lambda 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 rozhraní .NET Framework 4, rozhraní API stromy výraz také podporuje přiřazení a řízení toku výrazy například smyčky, podmíněné bloky a try-catch bloků.Pomocí rozhraní API, můžete vytvořit stromy výrazů, které jsou komplexnější než tvary, které mohou být vytvořeny z lambda výrazy kompilátoru jazyka C# a Visual Basic.Následující příklad ukazuje, jak vytvořit strom výrazu, který vypočítá faktoriál čí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 tématu generování dynamické metody s stromy výrazů v sadě Visual Studio 2010.

Analýza stromy výrazů

Následující příklad kódu ukazuje, jak výraz stromové struktury, která představuje výrazu lambda 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            

Neměnitelnosti stromy výrazů

Stromy výrazů by měl být neměnitelný.To znamená, že pokud chcete změnit strom výrazu, je nutné zkopírováním existující a nahrazování uzly v něm vytvořit nový strom výrazu.Návštěvníka strom výrazu slouží k procházení na stávající strom výrazu.Další informace naleznete v tématu Postupy: Úpravy stromů výrazů (C# a Visual Basic).

Kompilování stromy výrazů

Expression Typ poskytuje Compile metodu, která kompiluje kód reprezentována strom výrazu do spustitelného delegáta.

Následující příklad kódu ukazuje, jak zkompilovat strom výrazu 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 Postupy: Provádění stromů výrazů (C# a Visual Basic).

Viz také

Úkoly

Postupy: Provádění stromů výrazů (C# a Visual Basic)

Postupy: Úpravy stromů výrazů (C# a Visual Basic)

Referenční dokumentace

Výrazy Lambda (Průvodce programováním v C#)

System.Linq.Expressions

Koncepty

Přehled DLR (Dynamic Language Runtime)

Lambda – výrazy (Visual Basic)

Další zdroje

Základy strom výrazu

Generování dynamické metody s stromy výrazů v sadě Visual Studio 2010

Koncepty programování