2012-01-24 156 views
26

LINQ表達式樹是否有適當的樹,如圖,(無論指導與否,維基百科似乎不太贊同)沒有周期?什麼是來自以下C#表達式的表達式樹的根?LINQ表達式樹是否合適樹?

(string s) => s.Length 

表達式樹看起來像這樣,「 - >」表示可以通過其他節點訪問的節點的屬性名稱。

 ->Parameters[0] 
Lambda---------Parameter(string s) 
    \    /
    \->Body  /->Expression 
     \   /
     Member(Length) 

當使用ExpressionVisitor訪問LambdaExpression時,ParameterExpression被訪問兩次。有沒有一種方法可以使用ExpressionVisitor來訪問LambdaExpression,以便所有節點只訪問一次,並以特定的已知順序(預訂,按順序,後序等)訪問?

+0

爲什麼你需要這個,你爲什麼在意? –

+4

@DanielHilgarth我認爲這是一個關於表達式樹的基本概念如何工作的合理問題。這是一個問答網站,看起來提問者好奇表達式樹是如何工作的。 –

+0

可能是這個問題是爲了投票,但它很有趣。 –

回答

17

排序,是的。 LambdaExpression的實際「中繼線」(如果您願意的話)是.Body;這些參數是關於樹結構(以及它需要的)的必要元數據,但頂部(虛線)的.Parameters並不是樹的功能圖的一部分 - 只有當這些節點稍後用於他們感興趣的樹的實際身體,作爲價值替代品。

的​​被訪問兩次是必需的,因此,這是可能是有人掉的參數,如果他們想要的 - 例如,與相同數量的參數來構建一個全新的LambdaExpression,但不同的參數情況下(也許改變方式)。

訂單將相當穩定,但應視爲實施細節。例如,給定一個節點(如Add(A,B)),不管我是否首先訪問A-first和B,它都不應該有任何語義差異。

+0

謝謝。很高興知道表達式類的哪些屬性在表達式樹中構成「正確」的邊。 – cynic

+0

@cynic幾乎所有不是'LambdaExpression.Parameters'的'Expression'!儘管我只是真正考慮3.5式的表達方式,但我無法想象其他任何人在我腦海之上。在某些4.0節點類型上可能會有其他類似的元數據值... –

17

只是到個位相加,以馬克的正確答案:

是否有向圖無環LINQ表達式樹?

首先,是的,表達式樹是一個DAG - 一個有向無環圖。

我們知道它們是非循環的,因爲表達樹是不變的,因此必須從葉子上構建。在這種情況下,沒有辦法做出一個循環,因爲所有的循環中的節點將不得不分配最後的,顯然這不會發生。

因爲這些部分是不可變的,所以表達式「樹」實際上不必是樹本身。正如馬克指出的那樣,您需要重新使用該參數的參考;這就是我們如何確定何時使用聲明的參數。雖然合法,但也有些奇怪的是重複使用其他部分。例如,如果您想要表示(int x)=>(x + 1) * (x + 1)正文的表達式樹,則可以爲(x + 1)創建一個表達式樹,然後創建一個乘法節點,其中兩個孩子都是該表達式樹。

當使用ExpressionVisitor訪問LambdaExpression時,ParameterExpression被訪問兩次。有沒有一種方法可以使用ExpressionVisitor來訪問LambdaExpression,以便所有節點只訪問一次,並以特定的已知順序(預訂,按順序,後序等)訪問?

ExpressionVisitor是一個抽象類。你可以自己製作具有你喜歡的語義的具體版本。例如,您可以重寫Visit方法,使其維護已經看到的節點的HashSet,並且不會在先前接受的節點上調用Accept。

+0

感謝@ericlippert,這使得它更加清晰。還有一個問題是:在第二個(不是嵌套的)lambda中重複使用相同的參數實例,甚至是在第二個lambda參數集合中使用它是否可以? lambda1:(x)=> x.Y lambda2:(x)=> x.Z 用於source.Where(lambda1).OrderBy(lambda2) 這是C#LINQ不會產生的東西。但它被認爲是一個有效的表達樹? – Tom67

+1

@ Tom67:**這是一個問題和答案網站。**發佈該問題! –

+1

謝謝@ericlippert,現在我希望得到最終答案[here](http://stackoverflow.com/questions/18911304/should-linq-lambda-expression-parameters-be-reused-in-a-second-lambda )。 – Tom67