共用方式為


運算式樹狀架構 (C# 和 Visual Basic)

運算式樹狀架構代表類似樹狀目錄之資料結構中的程式碼,其中,每個節點都是一個運算式,例如,方法呼叫或二進位運算 (如 x < y)。

您可以編譯和執行運算式樹狀架構所代表的程式碼。 這會啟用動態修改可執行程式碼、在各種資料庫中執行 LINQ 查詢,以及建立動態查詢。 如需 LINQ 中運算式樹狀架構的詳細資訊,請參閱 如何:使用運算式樹狀結構建置動態查詢 (C# 和 Visual Basic)

運算式樹狀架構也用於動態語言執行階段中,以提供動態語言與 .NET Framework 之間的互通性,並讓編譯器寫入器發出運算式樹狀架構,而不是 Microsoft Intermediate Language (MSIL)。 如需 DLR 的詳細資訊,請參閱 Dynamic Language Runtime 概觀

您可以根據匿名 Lambda 運算式讓 C# 或 Visual Basic 編譯器建立運算式樹狀架構,也可以使用 System.Linq.Expressions 命名空間以手動建立運算式樹狀架構。

從 Lambda 運算式建立運算式樹狀架構

將 Lambda 運算式指派給類型為 Expression 的變數時,編譯器會發出程式碼,以建置代表 Lambda 運算式的運算式樹狀架構。

C# 和 Visual Basic 編譯器只能從運算式 Lambda (或單行 Lambda) 產生運算式樹狀架構。 它無法剖析陳述式 Lambda (或多行 Lambda)。 如需 C# 中 Lambda 運算式的詳細資訊,請參閱 Lambda 運算式 (C# 程式設計手冊);對於 Visual Basic,請參閱 Lambda 運算式 (Visual Basic)

下列程式碼範例示範如何讓 C# 和 Visual Basic 編譯器建立代表 Lambda 運算式 num => num < 5 (C#) 或 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;

使用 API 建立運算式樹狀架構

若要使用 API 建立運算式樹狀架構,請使用 Expression 類別。 這個類別包含可建立之特定類型運算式樹狀架構節點的靜態 factory 方法,例如,ParameterExpression (代表變數或參數) 或 MethodCallExpression (代表方法呼叫)。 ParameterExpression, MethodCallExpression 和其他運算式特定類型也定義在 System.Linq.Expressions 命名空間中。 這些類型衍生自抽象類型 Expression

下列程式碼範例示範如何使用 API 來建立代表 Lambda 運算式 num => num < 5 (C#) 或 Function(num) num < 5 (Visual Basic) 的運算式樹狀架構。

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

在.NET Framework 4 中,運算式樹狀架構 API 也支援指派以及控制流程運算式 (例如迴圈、條件式區塊和 try-catch 區塊)。 使用 API 所建立的運算式樹狀架構,會比 C# 和 Visual Basic 編譯器可以從 Lambda 運算式所建立的運算式樹狀架構還要複雜。 下列範例示範如何建立可計算數字階乘的運算式樹狀架構。

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

如需詳細資訊,請參閱在 Visual Studio 2010 中使用運算式樹狀架構產生動態方法

剖析運算式樹狀架構

下列程式碼範例示範如何將代表 Lambda 運算式 num => num < 5 (C#) 或 Function(num) num < 5 (Visual Basic) 的運算式樹狀架構分解成其各部份。

        ' 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            

運算式樹狀架構的不變性

運算式樹狀架構應該是不變的。 這表示,如果您要修改運算式樹狀架構,則必須複製現有運算式樹狀架構,並取代其中的節點,以建構新的運算式樹狀架構。 您可以使用運算式樹狀架構訪問項來周遊現有運算式樹狀架構。 如需詳細資訊,請參閱如何:修改運算式樹狀架構 (C# 和 Visual Basic)

編譯運算式樹狀架構

Expression 類型提供 Compile 方法,以將運算式樹狀架構所代表的程式碼編譯為可執行委派。

下列程式碼範例示範如何編譯運算式樹狀架構,並執行產生的程式碼。

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

如需詳細資訊,請參閱如何:執行運算式樹狀結構 (C# 和 Visual Basic)

請參閱

工作

如何:執行運算式樹狀結構 (C# 和 Visual Basic)

如何:修改運算式樹狀架構 (C# 和 Visual Basic)

參考

Lambda 運算式 (C# 程式設計手冊)

System.Linq.Expressions

概念

Dynamic Language Runtime 概觀

Lambda 運算式 (Visual Basic)

其他資源

運算式樹狀架構基礎

在 Visual Studio 2010 中使用運算式樹狀架構產生動態方法

程式設計概念