Udostępnij za pośrednictwem


Wyrażenie drzew (C# i Visual Basic)

Wyrażenia drzewa reprezentują takie jak kod w strukturze drzewa danych, gdzie każdy węzeł jest wyrażenie, na przykład, wywołanie metody lub operacji binarny x < y.

Można skompilować i uruchomić kod reprezentowane przez wyrażenie drzew.Umożliwia dynamiczne modyfikacji kodu wykonywalnego, wykonanie LINQ kwerend w różnych bazach danych i tworzenia kwerend dynamicznych.Aby uzyskać więcej informacji na temat drzew wyrażenie LINQ, zobacz Jak: tworzenie kwerend dynamicznych (C# i Visual Basic) przy użyciu wyrażenia drzewa i Instruktaż: Tworzenie dostawcą IQueryable LINQ.

Wyrażenia drzewa są również używane w aparat plików wykonywalnych języka dynamicznego (DLR) aby zapewnić współdziałanie między językami dynamiczne i.NET Framework i umożliwiające pisarzy kompilatora do emitowania wyrażenie drzewa zamiast Microsoft pośrednie języka (MSIL).Aby uzyskać więcej informacji na temat DLR, zobacz Omówienie środowiska wykonawczego języka dynamicznego.

Może mieć kompilator C# lub Visual Basic tworzenie drzewa wyrażenie, oparte na wyrażenie lambda anonimowych lub drzew wyrażenie można utworzyć ręcznie za pomocą System.Linq.Expressions obszaru nazw.

Tworzenie wyrażenia drzewa z wyrażenia Lambda

Gdy wyrażenie lambda jest przypisana do zmiennej typu Expression<TDelegate>, kompilator generuje kod do konstruowania drzewa wyrażenia, która reprezentuje wyrażenie lambda.

C# i Visual Basic kompilatory można wygenerować drzewa wyrażenie tylko z wyrażenia lambdas (lub lambdas w pojedynczym wierszu).To nie można przeanalizować lambdas instrukcję (lub wielowierszowego lambdas).Aby uzyskać więcej informacji na temat lambda wyrażenia w języku C#, zobacz Wyrażenia lambda (Podręcznik programowania C#); dla języka Visual Basic, zobacz Wyrażenia lambda (Visual Basic).

W poniższych przykładach kodu pokazano sposób mieć C# i programów kompilujących w języku Visual Basic tworzenie drzewa wyrażenia, która reprezentuje wyrażenie lambda num => num < 5 (C#) lub 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;

Tworzenie drzewa wyrażenie przy użyciu interfejsu API

Aby utworzyć wyrażenie drzewa za pomocą interfejsu API, użyj Expression klasy.Ta klasa zawiera metody statyczne factory, które utworzyć wyrażenie węzłów drzewa określonych typów, na przykład, ParameterExpression, który reprezentuje zmienną lub parametr, lub MethodCallExpression, który reprezentuje wywołanie metody.ParameterExpression, MethodCallExpression, i inne typy specyficzne dla wyrażenia są również określone w System.Linq.Expressions obszaru nazw.Te typy pochodzić od typu abstract Expression.

Poniższy przykład kodu demonstruje, jak utworzyć drzewo wyrażenia, która reprezentuje wyrażenie lambda num => num < 5 (C#) lub Function(num) num < 5 (Visual Basic) przy użyciu interfejsu 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 });

W programie.NET Framework 4, wyrażenie API drzew obsługuje również przypisań i kontroli przepływu wyrażeń takich jak pętle i bloki warunkowe i try-catch bloków.Korzystając z interfejsu API, można utworzyć wyrażenie drzew, które są bardziej złożone niż te, które mogą być tworzone z wyrażenia lambda przez kompilatory C# i Visual Basic.Poniższy przykład ilustruje sposób utworzyć drzewo wyrażenie, służącą do obliczania silni liczby.

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

Aby uzyskać więcej informacji, zobacz Metody dynamicznego generowania drzewami wyrażenie w Visual Studio 2010.

Podczas analizowania drzewa wyrażenie

Poniższy przykład kodu pokazuje, jak wyrażenie drzewa, która reprezentuje wyrażenie lambda num => num < 5 (C#) lub Function(num) num < 5 (Visual Basic) może być rozłożony na jego części.


        ' 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            

Niezmienność drzew wyrażenie

Wyrażenia drzewa powinny być niezmienne.Oznacza to zmodyfikować wyrażenie drzewa, przez kopiowanie istniejącego i zastępowanie węzłów w nim należy tworzyć nowego drzewa w wyrażeniu.Przechodzenie do istniejącego drzewa wyrażenie, można użyć przez osobę odwiedzającą drzewa wyrażenie.Aby uzyskać więcej informacji, zobacz Jak: Modyfikowanie wyrażenia drzew (C# i Visual Basic).

Kompilowanie drzew wyrażenie

Expression<TDelegate> Zawiera typ Compile metodę, która kompiluje kod, reprezentowany przez drzewo wyrażenie do pełnomocnika pliku wykonywalnego.

Poniższy przykład kodu demonstruje, jak skompilować wyrażenia drzewa i uruchomić kod wynikowy.

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

Aby uzyskać więcej informacji, zobacz Jak: wykonywanie wyrażenie drzew (C# i Visual Basic).

Zobacz też

Zadania

Jak: wykonywanie wyrażenie drzew (C# i Visual Basic)

Jak: Modyfikowanie wyrażenia drzew (C# i Visual Basic)

Informacje

Wyrażenia lambda (Podręcznik programowania C#)

System.Linq.Expressions

Koncepcje

Omówienie środowiska wykonawczego języka dynamicznego

Wyrażenia lambda (Visual Basic)

Inne zasoby

Podstawowe informacje o wyrażenie drzewa

generowania metod dynamicznych z drzew wyrażenie w Visual Studio 2010

Pojęcia związane z programowaniem