Passing Func<> to IQueryable vs Expression<Func<
本文关键字:lt Func vs Expression IQueryable gt Passing to | 更新日期: 2023-09-27 18:14:10
我开始在LINQ的引子下多看一点,我很难理解一些LINQ扩展方法的重载。
例如,假设我正在使用. where()查询DbContext。我总是传递一个标准的Func<>,而不是所述Func<>的表达式<>。下面的查询示例:
var db = new MyContext();
var foo = db.products.Where(p => p.Category == "books");
这就是我困惑的地方。当我查看可用的方法签名时,我会假设我上面使用的重载将返回我一个IEnumerable…但它实际上返回了一个IQueryable。这是怎么可能的,如果IQueryable重载期待一个表达式,而不是只是一个函数?感觉编译器在某种程度上帮助了我(在这种情况下)构建表达式,但我找不到解释这种情况的资源。谢谢!
感觉编译器在某种程度上帮助了我(在这种情况下)构建表达式
这正是正在发生的事情。编译器可以将lambdas(只要它们没有"语句体")解释为委托或表达式树。Queryable.Where<T>(this IQuerayble<T>, ...)
扩展方法优先于Enumerable.Where<T>(this IEnumerable<T>, ...)
扩展方法,因此编译器选择将谓词解释为表达式树。
感觉编译器在某种程度上帮助了我(在这种情况下)构建表达式
正确,编译器将lambda编译为Expression
而不是Func
。
从MSDN:我找不到解释这种情况的资源
当将lambda表达式赋值给
Expression<TDelegate>
类型的变量时,编译器发出代码来构建表示该lambda表达式的表达式树。
在该示例中,您没有传递Func
。你正在通过Expression
。lambda可以根据其周围的上下文编译为委托或表达式。在这种情况下,它周围的上下文期望一个表达式,所以这就是lambda编译成的。如果您实际上确实传递了Func
而不是lambda(可能是两者之一),那么您将获得IEnumerable
的结果,而不是IQueryable
。
编译器可以从lamba表达式自动为你构建一个表达式树,这就是这里发生的事情。
http://msdn.microsoft.com/en-gb/library/bb397951.aspx