表示式樹狀結構代表類似樹狀數據結構中的程式代碼,其中每個節點都是表達式,例如方法呼叫或二進位作業,例如 x < y。
您可以編譯和執行運算式樹狀架構所代表的程式代碼。 這可讓您動態修改可執行的程式代碼、在各種資料庫中執行LINQ查詢,以及建立動態查詢。 如需 LINQ 中表示式樹狀架構的詳細資訊,請參閱 如何:使用表示式樹狀架構建置動態查詢 (Visual Basic) 。
表達式樹狀架構也用於動態語言執行平臺 (DLR) 中,以提供動態語言與 .NET Framework 之間的互作性,並讓編譯程式寫入器發出表達式樹狀架構,而不是通用中繼語言 (CIL)。 如需 DLR 的詳細資訊,請參閱 動態語言執行平臺概觀。
您可以讓 C# 或 Visual Basic 編譯程式根據匿名 Lambda 運算式為您建立表示式樹狀結構,也可以使用 命名空間手動 System.Linq.Expressions 建立表達式樹狀結構。
從 Lambda 運算式建立表達式樹
將 Lambda 運算式指派給 類型的 Expression<TDelegate>變數時,編譯程式會發出程式代碼來建置代表 Lambda 表達式的運算式樹狀結構。
Visual Basic 編譯器只能從表達式 lambda(或單行 lambda)產生表達式樹。 它無法解析語句 lambda 表達式(或多行 lambda 表達式)。 如需 Visual Basic 中 Lambda 表達式的詳細資訊,請參閱 Lambda 運算式。
下列程式代碼範例示範如何讓 Visual Basic 編譯程式建立代表 Lambda 運算式 Function(num) num < 5的運算式樹狀結構。
Dim lambda As Expression(Of Func(Of Integer, Boolean)) =
Function(num) num < 5
使用 API 創建運算式樹
若要使用 API 建立運算式樹狀結構,請使用 類別 Expression 。 這個類別包含靜態處理站方法,這些方法會建立特定類型的表達式樹狀節點,例如 , ParameterExpression代表變數或參數,或 MethodCallExpression,代表方法呼叫。 ParameterExpression、MethodCallExpression和其他運算式相關的型別也會在 System.Linq.Expressions 命名空間中定義。 這些型別衍生自抽象型別 Expression。
下列程式代碼範例示範如何使用 API 建立代表 Lambda 運算式 Function(num) num < 5 的運算式樹狀結構。
' 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})
在 .NET Framework 4 或更新版本中,表達式樹狀架構 API 也支援指派和控制流程表達式,例如迴圈、條件式區塊和 try-catch 區塊。 藉由使用 API,您可以建立比 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.
如需詳細資訊,請參閱 在Visual Studio 2010中使用表達式樹狀架構產生動態方法,這也適用於較新版本的Visual Studio。
剖析表達式樹狀結構
下列程式代碼範例示範如何將代表 Lambda 運算式 Function(num) num < 5 的表達式樹狀結構分解成其元件。
' 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
表達式樹狀架構的不變性
表達式樹狀架構應該是不可變的。 這表示如果您想要修改表達式樹狀結構,您必須複製現有的表達式樹狀結構並取代其中節點,以建構新的表達式樹狀結構。 您可以使用表達式樹狀結構訪問器來遍歷現有的表達式樹狀結構。 如需詳細資訊,請參閱 如何:修改表達式樹狀架構 (Visual Basic)。
編譯表達式樹
Expression<TDelegate> 類型提供 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.
如需詳細資訊,請參閱 如何:執行表達式樹狀架構 (Visual Basic)。