我理解lambdas和Func和Action委托。但表情 我头疼不已。
在什么情况下,你会使用表达式<Func<T>>而不是普通的旧Func<T>?
我理解lambdas和Func和Action委托。但表情 我头疼不已。
在什么情况下,你会使用表达式<Func<T>>而不是普通的旧Func<T>?
当前回答
在选择表达式和Func时,一个非常重要的考虑因素是IQueryable提供者,如LINQ to Entities可以“消化”你在表达式中传递的内容,但会忽略你在Func中传递的内容。关于这个主题,我有两篇博文:
更多关于表达式vs函数与实体框架和 爱上LINQ -第7部分:表达式和功能函数(最后一部分)
其他回答
在Krzysztof Cwalina的书(框架设计指南:可重用的。net库的约定、习惯用法和模式)中有一个更哲学的解释;
编辑非图像版本:
大多数情况下,如果你只需要运行一些代码,你就需要Func或Action。当代码在运行之前需要分析、序列化或优化时,就需要使用Expression。表达式是用来思考代码的,Func/Action是用来运行代码的。
主要原因是当您不想直接运行代码,而是想检查它时。这可能有很多原因:
Mapping the code to a different environment (ie. C# code to SQL in Entity Framework) Replacing parts of the code in runtime (dynamic programming or even plain DRY techniques) Code validation (very useful when emulating scripting or when doing analysis) Serialization - expressions can be serialized rather easily and safely, delegates can't Strongly-typed safety on things that aren't inherently strongly-typed, and exploiting compiler checks even though you're doing dynamic calls in runtime (ASP.NET MVC 5 with Razor is a nice example)
很高兴知道你可以使用Func<TEntity, bool>与AsQueryable()扩展方法,如Expression<Func<TEntity, bool>>。
Func<App, bool> filter = x => x.Alias.Contains("gan");
var query = dbSet.Where(filter).AsQueryable();
在使用Count()或ToList()等执行方法之前,查询不会被执行。
我想补充一些关于Func<T>和Expression<Func<T>>的区别:
Func<T> is just a normal old-school MulticastDelegate; Expression<Func<T>> is a representation of lambda expression in form of expression tree; expression tree can be constructed through lambda expression syntax or through the API syntax; expression tree can be compiled to a delegate Func<T>; the inverse conversion is theoretically possible, but it's a kind of decompiling, there is no builtin functionality for that as it's not a straightforward process; expression tree can be observed/translated/modified through the ExpressionVisitor; the extension methods for IEnumerable operate with Func<T>; the extension methods for IQueryable operate with Expression<Func<T>>.
有一篇文章用代码示例描述了细节: LINQ: Func<T> vs. Expression<Func<T>>。
希望对大家有所帮助。
当使用LINQ-to-SQL时,将Func<>s传递给Where()或Count()是不好的。真正的坏。如果你使用Func<>,那么它调用IEnumerable LINQ的东西,而不是IQueryable,这意味着整个表被拉进来,然后过滤。表达式<Func<>>明显更快,因为它在SQL服务器上执行过滤-特别是如果您正在查询位于另一个服务器上的数据库。