Stromy výrazů (Visual Basic)

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.

Kód reprezentovaný stromy výrazů můžete zkompilovat a spustit. To 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 Postupy: Použití stromů výrazů k vytváření dynamických dotazů (Visual Basic).

Stromy výrazů se také používají v modulu runtime dynamického jazyka (DLR) k zajištění interoperability mezi dynamickými jazyky a .NET Framework a k umožnění zapisovačů kompilátoru generovat stromy výrazů místo jazyka MSIL (Microsoft Intermediate Language). Další informace o DLR naleznete v tématu Přehled modulu runtime dynamického jazyka.

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

Vytváření stromů výrazů z výrazů lambda

Když 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.

Kompilátor Visual Basic může generovat stromy výrazů pouze z výrazů lambda (nebo jednořádkových lambda). Nemůže parsovat výrazy lambda (nebo víceřádkové lambda). Další informace o výrazech lambda v Visual Basic naleznete v tématu Výrazy lambda.

Následující příklady kódu ukazují, jak mít kompilátor Visual Basic vytvořit strom výrazu, který představuje výraz Function(num) num < 5lambda .

Dim lambda As Expression(Of Func(Of Integer, Boolean)) =  
    Function(num) num < 5  

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

Pokud chcete vytvořit stromy výrazů pomocí rozhraní API, použijte Expression třídu. Tato třída obsahuje statické metody továrny, které vytvářejí uzly stromu výrazů konkrétních typů, ParameterExpressionnapříklad , které představují proměnnou nebo parametr, nebo MethodCallExpression, který představuje volání metody. ParameterExpression, MethodCallExpressiona ostatní typy specifické pro výraz jsou také definovány System.Linq.Expressions v 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ýraz Function(num) num < 5 lambda 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})  

V .NET Framework 4 nebo novějším rozhraní API stromů výrazů podporuje také přiřazení a výrazy toku řízení, jako jsou smyčky, podmíněné bloky a try-catch bloky. Pomocí rozhraní API můžete vytvořit stromy výrazů, které jsou složitější než ty, které lze vytvořit z výrazů lambda kompilátorem Visual Basic. Následující příklad ukazuje, jak vytvořit strom výrazů, 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.  

Další informace najdete v tématu Generování dynamických metod pomocí stromů výrazů v Visual Studio 2010, které platí také pro novější verze Visual Studio.

Analýza stromů výrazů

Následující příklad kódu ukazuje, jak může být strom výrazu, který představuje výraz Function(num) num < 5 lambda, rozložen do jeho částí.

' 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  

Neměnnost stromů výrazů

Stromy výrazů by měly být neměnné. To znamená, že 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. K procházení existujícího stromu výrazů můžete použít návštěvníka stromu výrazů. Další informace najdete v tématu Postupy: Úprava stromů výrazů (Visual Basic).

Kompilace stromů výrazů

Typ Expression<TDelegate> poskytuje metodu Compile , která zkompiluje kód reprezentovaný stromem výrazu do spustitelného delegáta.

Následující příklad kódu ukazuje, jak zkompilovat strom výrazů 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.  

Další informace najdete v tématu Postupy: Spouštění stromů výrazů (Visual Basic).

Viz také