Returning IEnumerable when the object is an IQueryable
我对IEnumerable和
我有一个函数(
1 2 3 4 5 6 7 | IEnumerable<MyClass> GetMyClasses(int id) { return GetQuery().Where(p => p.Id==id); } IQueryable<MyClass> GetQuery() { // returns an IQueryable list here } |
现在我的问题是。假设我在这里返回一个IEnumerable而不是一个
有什么帮助,甚至是指向描述这个的资源的指针吗?
这篇文章很有帮助:linq to sql中的iqueryable与ienumerable。
引用这篇文章,"根据msdn文档,通过构建内部表达式树来调用iQueryable。"这些扩展IQueryable(of T)的方法不直接执行任何查询。相反,它们的功能是构建表达式对象,该对象是表示累积查询的表达式树。""
表达式树是C和.NET平台上非常重要的结构。(一般来说,它们很重要,但C使它们非常有用。)为了更好地理解这一区别,我建议阅读官方C 5.0规范中表达式和语句之间的差异。对于分支到lambda微积分的高级理论概念,表达式支持将方法作为一级对象。iqueryable和IEnumerable之间的区别集中在这一点上。iqueryable构建表达式树,而IEnumerable不构建表达式树,至少对于我们这些不在微软秘密实验室工作的人来说不构建表达式树。
这是另一篇非常有用的文章,详细介绍了推和拉的区别。(通过"推"和"拉",我指的是数据流的方向。.NET和C的反应式编程技术#
这是一篇非常好的文章,详细介绍了语句lambda和表达式lambda之间的区别,并更深入地讨论了表达式tres的概念:重新访问c委托、表达式树和lambda语句与lambda表达式。
你把事情搞得太复杂了。考虑以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 | public class Base { } public class Derived : Base { } public Base Method() { return GetOtherMethod(); } public Derived GetOtherMethod() { return new Derived (); } |
您不知道
因此,您的
when the statement is executed with a ToList() will the underlying SQL generated take into account the Id == id statement and so only return filter items
简短的回答是"是"。
只有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | IEnumerable<MyClass> GetMyClasses(int id) { return GetQuery().Where(p => p.Id==id); // this always will work as IQueryable and handled by provider (in case of EF - the DB query will be performed) } IEnumerable<MyClass> MoreRestrictions(int id) { return GetMyClasses(id) .ToList(); // result list will be filtered by Id } IEnumerable<MyClass> MoreRestrictions(int id) { return GetMyClasses(id) .Where(x=>x.IsActive) // this where will be performed in memory on results filtered by Id. .ToList(); } |
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //There is only one implementation of ToList() public List<T> ToList<T>(this IEnumerable<T> e) { var list = new List<T>(); var enumerator = e.GetEnumerator(); while (enumerator.MoveNext()) { var item = e.Current; list.Add(item); } return list; } //Implementation for IEnumerable public IEnumerable<T> Where<T>(this IEnumerable<T> e, Predicate predicate) { var enumerator = e.GetEnumerator(); while (enumerator.MoveNext()) { var item = e.Current; if (predicate(item)) yield return item; } } //Implementation for IQueryable public IQueryable<T> Where<T>(this IQueryable<T> e, Expression<Predicate> predicate) { MethodBase method = ...; // create generic method of Queryable.Where() return e.Provider .CreateQuery<T>(Expression.Call(null, method, e.Expression, Expression.Quote(predicate))); } |
iQueryable的