簡體   English   中英

用於Enumerable和Queryable擴展方法的Lambda表達式參數

[英]Lambda expression arguments for Enumerable and Queryable extension methods

Lambda表達式是一個匿名方法,在后台它是一個委托,因此我可以執行以下操作:

 delegate bool Foo(int x);

 Foo bar = x => x == 1;

將此委托傳遞給Enumerable擴展方法是很有意義的,因為典型的期望參數是Func ,它是委托的簡寫:

 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

但是,我不清楚如何將委托傳遞給像這樣的Queryable擴展方法:

 public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

此方法需要一個Expression<TDelegate>參數,但是傳入lambda表達式是完全合法的。 將lambda表達式Expression<TDelegate>轉換為Expression<TDelegate>以便可以被使用的機制是什么?

我對Queryable方法建立了表達式樹以供提供程序進行解析的事實非常熟悉,我只是對這一方面感到好奇,這一方面對我而言並不立即顯而易見。

更新

我對我的無知越來越不了解。 Lambda表達式不是委托,但可用於創建委托或表達式:

 Expression<Func<int, bool>> foo = c => c == 1;

編譯器是否根據上下文推斷類型? 我猜測一定是這樣,因為這是不合法的:

var foo = c => c == 1;

在規范中對此進行了描述:

4.6表達式樹類型

如果存在從lambda表達式到委托類型D的轉換,則也存在到表達式樹類型Expression<D> 將lambda表達式轉換為委托類型會生成引用了lambda表達式的可執行代碼的委托,而轉換為表達式樹類型則會創建lambda表達式的表達式樹表示形式。 表達式樹是lambda表達式的有效內存數據表示形式,並使lambda表達式的結構透明且顯式

因此,存在從lambda到兼容的表達式樹類型的轉換,並且編譯器發出等效的表達式樹而不是創建委托。

很簡單,您做不到。 但是,為了使IQueryable方法有用,VS2008及更高版本包含了一個聰明的編譯器技巧。 可以將作為單個語句的lambda expression分配給delegateExpression<TDelegate> 編譯器通常會提升表達式並創建一個方法。

但是對於一個Expression<TDelegate>的賦值,它將語句分解為它們的語法含義,並將其轉變為一個表達式樹。

例如

Func<int,int> func = x=>x*x;
Expression<Func<int,int>> expression = x=>x*x;

第一個可能會變成一個帶有亂碼名稱的靜態方法,例如:

private static int <B012>SomeMethod(int x){
   return x*x;
}

其中,第二條語句將轉換為:

ParameterExpression paramX = Expression.Parameter(typeof(int));
Expression<Func<int,int>> expression = Expression.Lambda<Func<int,int>>(
     Expression.Multiply(paramX,paramX),paramX);

但是你不能做:

expression = func;

這是無效的,因為funcdelegate 您可以執行以下操作:

func=expression.Compile()

將表達式編譯成函子。

**請注意,建議的轉換可能不是100%正確的。

他們這樣做的原因是允許LINQ-to-Objects(基本上是其他語言的Map / Reduce)共享與LINQ-To-Providers相同的友好語法。 因此,您可以編寫一條具有相同含義的語句,但可以更改過濾和轉換發生的位置。 GetEmployees().Where(e=>e.LastName=="Smith")可以讀取相同內容,但從理論上講可以描述在此框或數據庫上進行過濾,或者解析xml文件或任意數量的各種各樣的東西。

我認為這與如何在IQueryable上構建查詢有關。 該方法需要一個表達式樹,因為它可以在內部查看並進行結構化,以匹配更優化(可能)的查詢或更緊密地映射到基礎數據源。 因此,簡單地傳遞一個Func僅允許執行,而Expression < Func >允許可以觀察和執行的表達式樹。

另外,可能更接近回答您的確切問題, 請查看此SO發布

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM