Sdílet prostřednictvím


Výraz stromů (C# a Visual Basic)

Výraz stromy představují kód podobné stromu datové struktury, kde každý uzel je výraz, například, volání metody nebo binární operace jako x < y.

Lze kompilovat a spustit kód reprezentované výraz stromů.To umožňuje dynamické změny spustitelný kód spuštění LINQ dotazů v různých databází a vytváření dynamických dotazy.Další informace o výraz olivovníků LINQ viz Jak: použití výrazu stromy vytvářet dynamické dotazy (C# a Visual Basic) a Názorný postup: Vytváření poskytovatele IQueryable LINQ.

Výraz stromy používají také v dynamic language runtime (DLR) poskytovat interoperabilitu mezi dynamické jazyky a.NET Framework a Povolit kompilátor autoři k vyzařování výraz stromy namísto Microsoft zprostředkujících jazyk (MSIL).Zobrazit další informace o DLR Dynamický přehled Language Runtime.

Máte vytvořit ve stromu výraz založený na anonymní lambda výraz nebo výraz stromy lze vytvořit ručně pomocí kompilátoru C# nebo Visual Basic System.Linq.Expressions oboru názvů.

Vytvoření výrazu stromy z Lambda výrazů

Pokud je přiřazena proměnné typu lambda výraz Expression<TDelegate>, kompilátor vyzařuje kódu sestavení stromu výraz, který představuje lambda výraz.

C# a Visual Basic kompilátory lze generovat výraz stromy pouze z výrazu lambdas (nebo lambdas jeden řádek).Nelze analyzovat, příkaz lambdas (nebo lambdas na více řádků).Další informace o lambda výrazy v jazyce C# Lambda výrazy (Příručka programování C#); Visual Basic naleznete v Lambda výrazy (Visual Basic).

Kód následující příklady ukazují, jak jste C# a Visual Basic kompilátory vytvoření stromu výraz, který představuje lambda výraz num => num < 5 (C#) nebo 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;

Vytvoření výrazu stromů pomocí rozhraní API

Vytvořit výraz stromů pomocí rozhraní API Expression třídy.Tato třída obsahuje statické výrobních metod, které uzly stromu specifických typů, například vytvořit výraz ParameterExpression, která představuje proměnnou nebo parametr, nebo MethodCallExpression, která představuje volání metody.ParameterExpression, MethodCallExpression, a další výraz specifické typy jsou rovněž definovány v System.Linq.Expressions oboru názvů.Tyto typy odvodit z abstraktní typ Expression.

Následující příklad kódu ukazuje, jak vytvořit strom výraz, který představuje lambda výraz num => num < 5 (C#) nebo Function(num) num < 5 (Visual Basic) 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})

            // 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 });

V.NET Framework 4, rozhraní API výraz stromy také podporuje přiřazení a řízení toku výrazy například smyčky podmíněné bloky a try-catch bloky.Pomocí rozhraní API můžete vytvořit výraz stromů, které jsou složitější než ty, které mohou být vytvořeny z lambda výrazy kompilátorů C# a Visual Basic.Následující příklad ukazuje způsob vytvoření stromu výraz, který vypočítá faktoriál zadaného čí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.
// 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.

Další informace naleznete v Generování dynamického metody s výraz stromy v roce 2010 Visual Studio.

Analýza výraz stromy

Následující příklad kódu ukazuje, jak výraz strom, který představuje lambda výraz num => num < 5 (C#) nebo Function(num) num < 5 (Visual Basic) lze rozložit na jeho části.


        ' 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 výraz stromy

Výraz stromy by měly být neměnná.To znamená, že pokud chcete upravit ve stromu výraz, musí sestavit nového stromu výraz zkopírováním existující a uzly v jeho nahrazení.Můžete procházet existujícího stromu výraz návštěvník stromu výraz.Další informace naleznete v tématu Jak: Upravit výraz stromů (C# a Visual Basic).

Sestavování výrazu stromy

Expression<TDelegate> Typu Compile metoda, která je reprezentována ve stromu výraz do spustitelného delegát kód zkompiluje.

Následující příklad kódu ukazuje, jak ve stromu výraz sestavit 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.
// 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.

Další informace naleznete v tématu Jak: spustit výraz stromů (C# a Visual Basic).

Viz také

Úkoly

Jak: spustit výraz stromů (C# a Visual Basic)

Jak: Upravit výraz stromů (C# a Visual Basic)

Referenční dokumentace

Lambda výrazy (Příručka programování C#)

System.Linq.Expressions

Koncepty

Dynamický přehled Language Runtime

Lambda výrazy (Visual Basic)

Další zdroje

Základy stromu výraz

dynamické metody s výrazem stromy v roce 2010 Visual Studio generování

Koncepty programování.