2014-07-21 62 views
2

我開始在LINQ引擎下查看一些內容,並且我無法理解一些LINQ擴展方法重載。將Func <>傳遞給IQueryable與表達式<Func<>>

例如,假設我正在使用.Where()查詢DbContext。我總是通過標準Func <>,而不是所述Func <>的表達式<>。下面的示例查詢:

var db = new MyContext(); 
var foo = db.products.Where(p => p.Category == "books"); 

這裏就是我很困惑。當我查看可用的方法簽名時,我會假設上面使用的重載將返回給我一個IEnumerable ...但它實際上返回一個IQueryable。如果IQueryable超載期望表達式而不僅僅是一個Func,這怎麼可能?感覺像編譯器以某種方式幫助我(在這種情況下)爲我構建表達式,但是我找不到解釋這種情況的資源。謝謝!

+1

如果您正在使用實體框架,然後在查詢中使用函數求<>可不好。我們遇到了在lamda中使用Func <>查詢數據庫的情況。結果是EF將整個表返回給客戶端,然後在客戶端使用Func <>進行過濾。在使用實體框架時,您一定要使用表達式>。 –

回答

1

感覺就像編譯器以某種方式幫助我通過(在這種情況下)構建表達我

正確,編譯器編譯拉姆達爲Expression,而不是一個Func

我找不到解釋的資源,如果是這樣的話

MSDN

當一個lambda表達式被分配到Expression<TDelegate>類型的變量,編譯器發出代碼來構建表示lambda表達式的表達式樹。

2

感覺就像編譯器以某種方式幫助我通過(在這種情況下)構建表達我

即到底發生了什麼。編譯器可以將lambda表達式(只要它們沒有「語句體」)解釋爲委託或表達式樹。 Queryable.Where<T>(this IQuerayble<T>, ...)擴展方法優先於Enumerable.Where<T>(this IEnumerable<T>, ...)擴展方法,因此編譯器選擇將謂詞解釋爲表達式樹。

+0

謝謝你回答我的後續問題(構建Expression優先)。 – gerg

+0

@gerg否,不是說「構建表達式」優先;它是'IQuerayble :IEnumerable ';它是'IQuerayble '優先。表達式樹在*方法重載解析之後發生。 –

1

你是不是在該例子中傳遞Func。您正在傳遞Expression。 lambda可以根據它的上下文編譯成委託或表達式。在這種情況下,它周圍的上下文需要一個表達式,所以這是lambda編譯成的。如果您確實通過了Func而不是拉姆達(可能是),那麼您的結果將得到IEnumerable,而不是IQueryable

相關問題