![](/img/trans.png)
[英]Extension methods on enumerable-derived classes cannot infer type arguments
[英]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
分配給delegate
和Expression<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;
這是無效的,因為func
是delegate
。 您可以執行以下操作:
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.