Freigeben über


Ausdrucksbäume (Visual Basic)

Ausdrucksbäume stellen Code in einer baumartigen Datenstruktur dar, wobei jeder Knoten ein Ausdruck ist, z. B. ein Methodenaufruf oder ein binärer Vorgang wie x < y.

Sie können Code kompilieren und ausführen, der durch Ausdrucksstrukturen dargestellt wird. Dies ermöglicht die dynamische Änderung von ausführbarem Code, die Ausführung von LINQ-Abfragen in verschiedenen Datenbanken und die Erstellung dynamischer Abfragen. Weitere Informationen zu Ausdrucksstrukturen in LINQ finden Sie unter How to: Use Expression Trees to Build Dynamic Queries (Visual Basic).

Ausdrucksbäume werden auch in der dynamischen Sprachlaufzeit (DLR) verwendet, um Interoperabilität zwischen dynamischen Sprachen und dem .NET Framework bereitzustellen und Compilerautoren das Erstellen von Ausdrucksbäumen anstelle der gemeinsamen Zwischensprache (CIL) zu ermöglichen. Weitere Informationen zur DLR finden Sie unter Übersicht über die Dynamic Language Runtime.

Sie können mit dem C#- oder Visual Basic-Compiler eine Ausdrucksstruktur für Sie erstellen, die auf einem anonymen Lambda-Ausdruck basiert, oder Sie können Ausdrucksstrukturen manuell mithilfe des System.Linq.Expressions Namespace erstellen.

Ausdrucksstrukturen aus Lambda-Ausdrücken erstellen

Wenn einem Lambda-Ausdruck eine Variable vom Typ Expression<TDelegate>zugewiesen ist, gibt der Compiler Code aus, um eine Ausdrucksstruktur zu erstellen, die den Lambda-Ausdruck darstellt.

Der Visual Basic-Compiler kann Ausdrucksbäume nur aus Ausdruckslambdas (oder einzeiligen Lambdas) erstellen. Es kann keine Anweisungslambdas (oder mehrzeiligen Lambdas) analysieren. Weitere Informationen zu Lambda-Ausdrücken in Visual Basic finden Sie unter Lambda-Ausdrücke.

Die folgenden Codebeispiele veranschaulichen, wie der Visual Basic-Compiler eine Ausdrucksstruktur erstellt, die den Lambda-Ausdruck Function(num) num < 5darstellt.

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

Erstellen von Ausdrucksbäumen mithilfe der API

Verwenden Sie die Klasse Expression, um Ausdrucksbaumstrukturen mit der API zu erstellen. Diese Klasse enthält statische Factorymethoden, die Ausdrucksstrukturknoten bestimmter Typen erstellen, z. B. , ParameterExpressiondie eine Variable oder einen Parameter darstellt, oder MethodCallExpression, die einen Methodenaufruf darstellt. ParameterExpression, MethodCallExpressionund die anderen ausdrucksspezifischen Typen werden auch im System.Linq.Expressions Namespace definiert. Diese Typen werden vom abstrakten Typ Expressionabgeleitet.

Im folgenden Codebeispiel wird gezeigt, wie man mit der API eine Ausdrucksstruktur erstellt, die den Lambda-Ausdruck Function(num) num < 5 darstellt.

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

In .NET Framework 4 oder höher unterstützt die Ausdrucksbaumstruktur-API auch Zuweisungen und Ablaufsteuerungsausdrücke wie Schleifen, bedingte Blöcke und try-catch-Blöcke. Mithilfe der API können Sie Ausdrucksstrukturen erstellen, die komplexer sind als solche, die vom Visual Basic-Compiler aus Lambda-Ausdrücken erstellt werden können. Im folgenden Beispiel wird veranschaulicht, wie eine Ausdrucksbaumstruktur erstellt wird, welche die Fakultät einer Zahl berechnet.

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

Weitere Informationen finden Sie unter Generieren dynamischer Methoden mit Ausdrucksstrukturen in Visual Studio 2010, die auch für spätere Versionen von Visual Studio gelten.

Analysieren von Ausdrucksbaumstrukturen

Im folgenden Codebeispiel wird veranschaulicht, wie die Ausdrucksstruktur, die den Lambda-Ausdruck Function(num) num < 5 darstellt, in seine Teile zerlegt werden kann.

' 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

Unveränderlichkeit von Ausdrucksbaumstrukturen

Ausdrucksbaumstrukturen sollten unveränderlich sein. Dies bedeutet, dass Sie, wenn Sie eine Ausdrucksstruktur ändern möchten, eine neue Ausdrucksstruktur erstellen müssen, indem Sie die vorhandene struktur kopieren und Knoten darin ersetzen. Sie können einen Ausdrucksbaumstruktur-Besucher verwenden, um die vorhandene Ausdrucksbaumstruktur zu durchlaufen. Weitere Informationen finden Sie unter How to: Modify Expression Trees (Visual Basic).

Kompilieren von Ausdrucksbäumen

Der Expression<TDelegate> Typ stellt die Methode Compile bereit, die den durch einen Ausdrucksbaum dargestellten Code in einen ausführbaren Delegaten kompiliert.

Im folgenden Codebeispiel wird veranschaulicht, wie Sie einen Ausdrucksbaum kompilieren und den resultierenden Code ausführen.

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

Weitere Informationen finden Sie unter How to: Execute Expression Trees (Visual Basic).

Siehe auch