备忘录23——Excalibur!!不对,是Expression!!"/>
B\S备忘录23——Excalibur!!不对,是Expression!!
上次是说明了一下下整个解决问题的过程是什么,总的来说还是从怀疑触发,验证怀疑的正确性,分而治之,这么看来跟平时写代码的习惯差不多嘛。
写代码就是个滚雪球的效应,雪球越滚越大,逻辑越写越复杂,但是复杂的逻辑是通过简单的代码一点点演化来的,前期压着打,中期带线、单抓扩大优势,后期一波完美团战直接上高,GG。。。好像一不小心又写到了熟悉的地方了。
好了,不说那么远了,先来说说上次留下的问题。
Func<T,TResult> 和 Expression<Func<T,TResult>>。
Func这个是一个委托,T表示委托的参数类型,TResult表示委托的返回值类型,这种用法直接就相当于生命了一个委托,并且要有返回值。
Expression<Func<T,TResult>>是表达式,它与Func并不相同,它表示一种lambda表达式的树形结构,这个树形结构描述了lambda表达式的作用,而不是执行它们。它基本上是描述这个表达式的组成,变量,调用方式等数据(例如:这个lambda表达式是由一些常数和一些参数构成的)。当然这种把lambda表达式转换成匿名函数或是Expression表达式的行为,也是要消耗编译时间的。
我们可以基于这种描述,来把它翻译成真正的方法来执行,或者做一些其他的事情,例如:Linq to SQL。微软提供了一种专门执行这种表达式的方法,Expression.Compile()。
EF在实现Linq to SQL操作的时候是根据表达式树来创建SQL语句,我们的底层使用的返回值都是IQueryable<T>这种类型,我查到了EF里面关于这个类型的源码,发现它的构造函数使用的就是表达式类型的。
// Type: System.Linq.Queryable
// Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll
public static class Queryable
{public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate){return source.Provider.CreateQuery<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression, Expression.Quote(predicate) }));}
}
而Func也有一种类型使用它,IEnumerable。
// Type: System.Linq.Enumerable
// Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll
public static class Enumerable
{public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate){return (IEnumerable<TSource>) new Enumerable.WhereEnumerableIterator<TSource>(source, predicate);}
}
所以啦,以后使用IQueryable就用Expression,IEnumberable就用Func。
最后,所有的资料我都是从外文的网站上查出来的,希望渣翻译没有错。别误导大家。
.html
更多推荐
B\S备忘录23——Excalibur!!不对,是Expression!!
发布评论