Udostępnij za pośrednictwem


Drzewa wyrażeń (C# i Visual Basic)

Drzewa wyrażeń reprezentuje kod struktura drzewa danych, gdzie każdy węzeł jest wyrażenia, na przykład, wywołania metody lub operację binarną takich jak x < y.

Można kompilować, a następnie uruchomić kod reprezentowanego przez wyrażenie drzewa.Umożliwia dynamiczne modyfikacji kodu wykonywalnego wykonywania LINQ kwerendę w różnych baz danych i tworzenie dynamicznych kwerend.Aby uzyskać więcej informacji na temat drzewa wyrażeń w składniku LINQ, zobacz Porady: używanie drzew wyrażeń do kompilowania zapytań dynamicznych (C# i Visual Basic).

Drzewa wyrażeń wymagają również są używane w dynamicznego środowiska uruchomieniowego języka (DLR), do zapewnienia współdziałanie dynamicznego języków i .NET Framework i umożliwiają twórcom kompilatorów emitować drzewa wyrażeń, a nie firmy Microsoft pośrednim języka (MSIL).Aby uzyskać więcej informacji na temat DLR, zobacz Przegląd środowiska uruchomieniowego języka dynamicznego.

Masz kompilatora C# lub Visual Basic, utwórz drzewo wyrażeń dla użytkownika w zależności od wyrażenia lambda anonimowy lub drzewa wyrażeń można utworzyć ręcznie za pomocą System.Linq.Expressions przestrzeni nazw.

Tworzenie drzewa wyrażeń z wyrażenia Lambda

Jeśli wyrażenia lambda jest przypisana do zmiennej typu Expression, kompilator emituje kod, by tworzyć drzewo wyrażeń, który reprezentuje wyrażenie lambda.

C# i Visual Basic kompilatorów może powodować generowanie drzewa wyrażeń tylko z wyrażenia lambdas (lub jeden wiersz lambdas).Go nie można przeanalizować instrukcji lambdas (lub lambdas wielowierszowego).Aby uzyskać więcej informacji na temat wyrażenia lambda w języku C#, zobacz Wyrażenia lambda (Przewodnik programowania w języku C#); dla języka Visual Basic, zobacz Lambda — Wyrażenia (Visual Basic).

W poniższych przykładach kodu pokazano sposób ma C# i Visual Basic kompilatorów Utwórz drzewo wyrażeń, który 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żeń, korzystając z interfejsu API

Aby utworzyć drzewa wyrażeń, korzystając z interfejsu API, należy użyć Expression klasy.Ta klasa zawiera metody statyczne fabryki, służące do tworzenia wyrażenia węzłów drzewa określonego typu, na przykład ParameterExpression, który reprezentuje zmienną lub parametr, lub MethodCallExpression, który reprezentuje wywołanie metody.ParameterExpression, MethodCallExpression, oraz inne typy specyficzny dla wyrażenia również są definiowane w System.Linq.Expressions przestrzeni nazw.Te typy pochodzić z typu abstrakcyjnego Expression.

Poniższy przykładowy kod przedstawia sposób tworzenia drzewo wyrażeń, który 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 z interfejsu API drzewa wyrażeń obsługuje także przypisania i kontroli przepływu wyrażeń, takich jak pętle, bloki warunkowych i try-catch bloków.Korzystając z interfejsu API, można utworzyć drzewa wyrażeń, które są bardziej złożonych niż te, które mogą być utworzone z wyrażenia lambda kompilatorów języka C# i Visual Basic.Poniższy przykład przedstawia sposób tworzenia drzewo wyrażeń, które oblicza 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 generowania metody dynamicznej z drzewa wyrażeń w programie Visual Studio 2010.

Analiza drzewa wyrażeń

Poniższy przykładowy kod przedstawia sposób wyrażenie drzewa, który reprezentuje wyrażenie lambda num => num < 5 (C#) lub Function(num) num < 5 (Visual Basic) może być rozłożone 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            

Immutability drzew wyrażenie

Drzewa wyrażeń powinno być niezmienialne.Oznacza to zmodyfikować drzewo wyrażeń, przez skopiowanie istniejącego i zastępowanie węzły w nim należy tworzyć nowe drzewo wyrażeń.Obiekt odwiedzający drzewa wyrażenie służy do przechodzenia w istniejącym drzewie wyrażenie.Aby uzyskać więcej informacji, zobacz Porady: modyfikowanie drzew wyrażeń (C# i Visual Basic).

Kompilowanie drzewa wyrażeń

Expression Zawiera typ Compile metody, która kompiluje kod reprezentowanego przez drzewo wyrażeń do pliku wykonywalnego delegata.

Poniższy przykładowy kod pokazuje, jak skompilować drzewo wyrażeń i wykonywania kodu wynikowego.

' 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 Porady: wykonywanie drzew wyrażeń (C# i Visual Basic).

Zobacz też

Zadania

Porady: wykonywanie drzew wyrażeń (C# i Visual Basic)

Porady: modyfikowanie drzew wyrażeń (C# i Visual Basic)

Informacje

Wyrażenia lambda (Przewodnik programowania w języku C#)

System.Linq.Expressions

Koncepcje

Przegląd środowiska uruchomieniowego języka dynamicznego

Lambda — Wyrażenia (Visual Basic)

Inne zasoby

Wyrażenie drzewa podstawy

Generowanie metody dynamicznej z drzewa wyrażeń w programie Visual Studio 2010

Koncepcje programowania