IEnumerable程序员
public interface IEnumerable<out T> : IEnumerable
ICollectionsql
public interface ICollection<T> : IEnumerable<T>, IEnumerable
IList函数
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
List性能
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
能够看到功能上List最强大,性能上IEnumerable更好,其实性能上都差很少,都是接口。spa
IEnumerable<T> 是linq to object。
IQueryable<T> 是linq to sql。.net
打个比方,我从Users中获取1条数据 var q=db.Users.orderby(x=>x.id).Take(1);
对于IEnumerable<T>来讲,他先会把全部数据加载到内存,而后在取一条数据。
对于IQueryable<T> 来讲,他会生成一个sql语句,只是取一条数据设计
留意 .net 的类库,会发现不多有方法返回 List<T> 或 IList<T> 的,可是不少 .net 的程序员喜欢这么作,为何?由于 List<T> 的功能实在太强大了吧。code
IEnumerable<T> 是延时求值的,若是在调用栈里面输入和输出都是 IEnumerable<T> 的话,是最好的,由于不管调用多少次,循环都只有一次,.NET 里面的 lambda 就是这样的。blog
可是调用栈的输入输出没法肯定的时候,状况就比较复杂。若是你返回的是 IEnumerable<T>,有可能调用栈的上一层执行了它的迭代器,形成并不须要的屡次循环。接口
若是调用栈的上一层使用的是 List<T> 的 Copy() 方法,那么你返回 List<T> 会比较好,若是你返回的是 IEnumerable<T>,通常是会被 ToList() 再 Copy()
因此这个问题关键仍是看怎么使用返回值,来决定你编写的函数的返回值。
使用尽量底层的、具体的类型。不要从一开始就超过你的需求来搞“抽象”。所以首先是使用 List<T>。
能返回List就不要返回IList:若是后面有方法须要IList能够直接传;若是后面须要用到List的属性就能直接用
若是返回的是IList:后面有方法须要List,你得想一想我能不能转,或者回去改;若是须要用到List的属性,还得回去改,综上考虑返回范围更广的类型好处多多。
可是,随着你真正开始须要抽象了,你就“被迫”须要重构为抽象的类型了。这时候再重构,要在必须的时候才进行抽象。真正会抽象的人,确定是反而不滥用抽象,是在必须的时候才抽象的。这个道理大概是“从不抽象设计”的人总也不能理解的。
有的人,很实际,你看到他的代码就知道他的这部分程序设计已经到达那个程度、必须抽象才能用在系统中。其返回的具体数据类型“确实是”多种子类型定义的,因此才抽象。这就是把复杂的接口弄得刚刚合适的声明程度。
而有的人,代码的抽象老是高于实际,中间存在着含糊的、不肯定的因素,明明其输入输出的数据类型不具备抽象、多态处理,却要弄一个很抽象的定义。这就是把简单的事情弄复杂了。
假设说你设计的时候,你有多种实际子类型的考虑,你确实有多种实现代码,那么你就返回一个枚举类型,明确地告诉使用者“我不能返回集合类型,我不保证明现全部的集合类型才有的功能”。这是由于你如今要实现的东西,确实是不能用集合类型的。
反过来讲,若是你输出的东西只能用集合类型,那么就返回集合类型,方便调用者傻瓜化地使用。未来还有其它复杂的扩展,那么应该重构接口,增长重载新方法,而不用去修改原来使用集合类型的东西。好比说 Linq 有一系列的基于枚举类型的功能方法,可是不是说原来基于集合类型而定义的一大堆方法就不该该设计出来。不须要放这个马后炮。因此根据如今实际状况,定义接口,习惯于常常在新版本中重构接口,而不是纠结在“一次性‘最完美’再也不变”的接口,就能够了。
好比多层项目中,数据层,业务层,展示层三层中,从数据层查询数据集到展示层须要“传递”2次,若是是List或者IEnumerable,会在数据层就将数据加载到内存,另外对于一个方法返回List集合,接受数据时每次都new 一个List集合 我感受是不妥的,若是数据量较大是很损性能。 而IQueryable对于数据的操做,会根据自定义的扩展方法 来生成最终的查询语句,而不是从一开始就加载数据,这就达到了哪里须要数据就在哪里查询。其实不少项目中都会有直接返回LIst的方法或者接口,这些方式不免是那些从培训中心历来的或者从一些书籍上看到的开发人员编写的。
抽象都是恰到好处地抽象,才叫抽象!