一、定义

IEnumerable

public interface IEnumerable<out T> : IEnumerable

ICollection

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更好,其实性能上都差不多,都是接口。

二、IEnumerable<T>和IQueryable<T> 的区别

IEnumerable<T> 是linq to object。
IQueryable<T> 是linq to sql。

打个比方,我从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> 的功能实在太强大了吧。

IEnumerable<T> 是延时求值的,如果在调用栈里面输入和输出都是 IEnumerable<T> 的话,是最好的,因为无论调用多少次,循环都只有一次,.NET 里面的 lambda 就是这样的。

但是调用栈的输入输出无法确定的时候,情况就比较复杂。如果你返回的是 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的方法或者接口,这些方式难免是那些从培训中心从来的或者从一些书籍上看到的开发人员编写的。

抽象都是恰到好处地抽象,才叫抽象!

基础知识---IEnumerable、ICollection、IList、IQueryable的更多相关文章

  1. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  2. 如何选择使用IEnumerable, ICollection, IList

    IEnumerable, ICollection, IList,每种接口只适合某些特定场景,如何区别使用呢? IEnumerable接口,只提供了一个获取迭代器的方法,这也是为什么可以使用foreac ...

  3. IEnumerable<> ICollection <> IList<> 区别

    IEnumerable< ICollection < IList区别 public interface IEnumerable { IEnumerator GetEnumerator(); ...

  4. 【转载】我也说 IEnumerable,ICollection,IList,List之间的区别

    做C#的同学们,都知道,一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 首先我看看 IEnumerable: / ...

  5. Asp.Net IEnumerable,ICollection,IList,List区别

    做C#的同学们,都知道,一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 首先我看看 IEnumerable: / ...

  6. IEnumerable,ICollection,IList,List区别

    做C#的同学们,都知道,一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 首先我看看 IEnumerable: / ...

  7. IEnumerable,ICollection,IList,List之间的区别

    做C#的同学们,都知道,一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 // 摘要: // 公开枚举器,该枚举器 ...

  8. IEnumerable,ICollection,IList,List的使用

    做C#的都知道:一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 首先我看看 IEnumerable:   // ...

  9. (原创)(C#随笔)IEnumerable< ICollection < IList区别

    public interface IEnumerable { IEnumerator GetEnumerator(); } 再看ICollection<T> public interfac ...

随机推荐

  1. GIT版本管理工具教程

    目录 GIT版本管理工具教程 一 Git初始化 二 简单指令使用 基本操作 简单总结 三 Git进阶 Git三大区域 Git回滚 Git分支 Git工作流 四 Github代码管理仓库 第一步:注册G ...

  2. Java自学-集合框架 ArrayList常用方法

    ArrayList常用方法 步骤 1 : 增加 add 有两种用法: 第一种是直接add对象,把对象加在最后面 heros.add(new Hero("hero " + i)); ...

  3. Vue Stomp+SocketJS 数据报错[Object object]

    开头一句mmp tmd换位置了也没个提示!!!! 坑死爹了 <template> <div> <input type="text" v-model=& ...

  4. React的jsx语法,详细介绍和使用方法!

    jsx语法 一种混合使用html及javascript语法的代码 在js中 遇到<xx>即开始html语法 遇到</xx>则结束html语法 恢复成js语法 例如: let D ...

  5. js 设计模式——代理模式

    代理模式 代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问. 生活中有很多的代理模式的场景.例如,明星有经纪人作为代理,老板有秘书作为代理等等,当有事情的时候,会找到经纪人或秘书,再由他 ...

  6. 实施一套MES系统需要多少钱?

    在制造业深耕的人都知道MES系统对于企业的重要性.MES生产执行系统是制造业生产现场透明化管理的最佳解决方案,制造业工厂通过实施MES系统可以解决生产计划.排产调度.工艺管理.品质管理.现场数据采集和 ...

  7. pipenv管理python开发环境

    简介 简单说,pipenv就是把pip和virtualenv包装起来的一个便携工具. 它不会在你的项目文件夹里生成一大堆东西,只有两个文本文件: Pipfile, 简明地显示项目环境和依赖包. Pip ...

  8. 系统级性能分析工具 — Perf【转】

    转自:https://blog.csdn.net/zhangskd/article/details/37902159 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn ...

  9. modbus_tk模块

    modbus_tk模块 通过modbus-RTU 读取地址,调用后返回反馈数值和故障信息. modbus_tk模块安装 pip install pymodbus_tk 下面代码功能:读取地址为0x42 ...

  10. Axel多线程工具安装

    Axel 是 Linux 下一个不错的轻量级高速下载工具,支持HTTP/FTP/HTTPS/FTPS协议,支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件. 大家使用 ...