Dela via


Uttrycksträd (Visual Basic)

Uttrycksträd representerar kod i en trädliknande datastruktur, där varje nod är ett uttryck, till exempel ett metodanrop eller en binär åtgärd som x < y.

Du kan kompilera och köra kod som representeras av uttrycksträd. Detta möjliggör dynamisk ändring av körbar kod, körning av LINQ-frågor i olika databaser och skapandet av dynamiska frågor. Mer information om uttrycksträd i LINQ finns i How to: Use Expression Trees to Build Dynamic Queries (Visual Basic).

Uttrycksträd används också i DLR (Dynamic Language Runtime) för att tillhandahålla samverkan mellan dynamiska språk och .NET Framework och för att göra det möjligt för kompilatorskrivare att generera uttrycksträd i stället för ett gemensamt mellanliggande språk (CIL). För mer information om DLR, se Översikt av dynamisk språkkörningsmiljö.

Du kan låta kompilatorn C# eller Visual Basic skapa ett uttrycksträd för dig baserat på ett anonymt lambda-uttryck, eller så kan du skapa uttrycksträd manuellt med hjälp System.Linq.Expressions av namnområdet.

Skapa uttrycksträd från Lambda-uttryck

När ett lambda-uttryck tilldelas en variabel av typen Expression<TDelegate>genererar kompilatorn kod för att skapa ett uttrycksträd som representerar lambda-uttrycket.

Visual Basic-kompilatorn kan endast generera uttrycksträd genom uttryckslambda-uttryck (eller enrads lambda-uttryck). Det går inte att parsa deklarations-lambdas (eller flerrads-lambdas). Mer information om lambda-uttryck i Visual Basic finns i Lambda-uttryck.

Följande kodexempel visar hur du får Visual Basic-kompilatorn att skapa ett uttrycksträd som representerar lambda-uttrycket Function(num) num < 5.

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

Skapa uttrycksträd med hjälp av API:et

Om du vill skapa uttrycksträd med hjälp av API:et använder du Expression klassen . Den här klassen innehåller statiska fabriksmetoder som skapar uttrycksträdnoder av specifika typer, ParameterExpressiontill exempel , som representerar en variabel eller parameter, eller MethodCallExpression, som representerar ett metodanrop. ParameterExpression, MethodCallExpression, och de andra uttrycksspecifika typerna definieras också i System.Linq.Expressions namnområdet. Dessa typer härleds från den abstrakta typen Expression.

Följande kodexempel visar hur du skapar ett uttrycksträd som representerar lambda-uttrycket Function(num) num < 5 med hjälp av API:et.

' 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})

I .NET Framework 4 eller senare stöder api:et för uttrycksträd även tilldelningar och kontrollflödesuttryck som loopar, villkorsblock och try-catch block. Med hjälp av API:et kan du skapa uttrycksträd som är mer komplexa än de som kan skapas från lambda-uttryck av Visual Basic-kompilatorn. I följande exempel visas hur du skapar ett uttrycksträd som beräknar faktorn för ett tal.

' 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.

Mer information finns i Generera dynamiska metoder med uttrycksträd i Visual Studio 2010, som även gäller för senare versioner av Visual Studio.

Parsning av uttrycksträd

Följande kodexempel visar hur uttrycksträdet som representerar lambda-uttrycket Function(num) num < 5 kan delas upp i dess delar.

' 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

Oföränderlighet för uttrycksträd

Uttrycksträd bör vara oföränderliga. Det innebär att om du vill ändra ett uttrycksträd måste du skapa ett nytt uttrycksträd genom att kopiera det befintliga och ersätta noder i det. Du kan använda en uttrycksträdsbesökare för att traversera det befintliga uttrycksträdet. Mer information finns i How to: Modify Expression Trees (Visual Basic).

Kompilera uttrycksträd

Typen Expression<TDelegate> innehåller Compile-metoden som kompilerar koden representerad av ett uttrycksträd till en körbar delegering.

I följande kodexempel visas hur du kompilerar ett uttrycksträd och kör den resulterande koden.

' 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.

Mer information finns i How to: Execute Expression Trees (Visual Basic).

Se även