2021年了,`IEnumerator`、`IEnumerable`还傻傻分不清楚?
IEnumerator、IEnumerable这两个接口单词相近、含义相关,傻傻分不清楚。
入行多年,一直没有系统性梳理这对李逵李鬼。
最近本人在怼着why神的《其实吧,LRU也就那么回事》,方案1使用数组实现LUR,手写算法涉及这一对接口,借此机会本次覆盖这一对难缠的冤家。
IEnumerator
IEnumerator、IEnumerable接口有相似的名称,这两个接口通常也在一起使用,它们有不同的用途。
IEnumerator接口为类内部的集合提供了迭代功能, IEnumerator 要求你实现三个方法:
MoveNext方法: 该方法将集合索引加1,并返回一个bool值,指示是否已到达集合的末尾。Reset方法: 它将集合索引重置为其初始值-1,这会使枚举数无效。Current方法: 返回position位置的当前对象
IEnumerable
IEnumerable接口为foreach迭代提供了支持,IEnumerable要求你实现GetEnumerator方法。
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
该用哪一个接口?
仅凭以上辞藻,很难区分两个接口的使用场景。
IEnumerator接口提供了对类中的集合类型对象的迭代,
IEnumerable接口允许使用foreach循环进行枚举。
但是,IEnumerable接口的GetEnumerator方法会返回一个IEnumerator接口。要实现IEnumerable,你还必须实现IEnumerator。如果你没有实现IEnumerator,你就不能将IEnumerable的GetEnumerator方法的返回值转换为IEnumerator接口。
从英文词根上讲:
IEnumerator接口代表了枚举器,里面定义了枚举方式;
IEnumerable接口代表该对象具备了可被枚举的性质。
总之,IEnumerable的使用要求类实现IEnumerator。如果您想提供对foreach的支持,那么就实现这两个接口。
最佳实践
- 在嵌套类中实现IEnumerator,这样你可以创建多个枚举器。
- 为IEnumerator的
Current方法提供异常处理。
为什么要这么做?
如果集合的内容发生变化,则reset方法将被调用,紧接着当前枚举数无效,您将收到一个IndexOutOfRangeException异常(其他情况也可能导致此异常)。所以执行一个Try…Catch块来捕获这个异常并引发InvalidOperationException异常, 提示在迭代时不允许修改集合内容。
这也正是我们常见的在foreach 里面尝试修改迭代对象会报
InvalidOperationException异常的原因。
下面以汽车列表为例实现IEnumerator IEnumerable接口
using System;
using System.Collections;
namespace ConsoleEnum
{
public class cars : IEnumerable
{
private car[] carlist;
//Create internal array in constructor.
public cars()
{
carlist= new car[6]
{
new car("Ford",1992),
new car("Fiat",1988),
new car("Buick",1932),
new car("Ford",1932),
new car("Dodge",1999),
new car("Honda",1977)
};
}
//private enumerator class
private class MyEnumerator:IEnumerator
{
public car[] carlist;
int position = -1;
//constructor
public MyEnumerator(car[] list)
{
carlist=list;
}
private IEnumerator getEnumerator()
{
return (IEnumerator)this;
}
//IEnumerator
public bool MoveNext()
{
position++;
return (position < carlist.Length);
}
//IEnumerator
public void Reset()
{
position = -1;
}
//IEnumerator
public object Current
{
get
{
try
{
return carlist[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
} //end nested class
public IEnumerator GetEnumerator()
{
return new MyEnumerator(carlist);
}
}
}
在foreach cars的时候,可以明显看到
- foreach语法糖初次接触cars, 实际会进入cars实现的 GetEnumerator()方法
- foreach每次迭代,实际会进入Current属性的get访问器
2021年了,`IEnumerator`、`IEnumerable`还傻傻分不清楚?的更多相关文章
- JS魔法堂:属性、特性,傻傻分不清楚
一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...
- Java:接口和抽象类,傻傻分不清楚?
01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...
- [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!
十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...
- 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】
文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...
- 傻傻分不清之 Cookie、Session、Token、JWT
傻傻分不清之 Cookie.Session.Token.JWT 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打 ...
- Shell中傻傻分不清楚的TOP3
Shell中傻傻分不清楚的TOP3 发布文章 近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Comm ...
- URI与URL傻傻分不清楚?
前言 总所周知,缓存是解决Http1.1协议传输性能的问题中最主要的手段. 缓存既可以存在于浏览器上,也可以存在于服务器中. 而影响缓存的Http头部有很多,其中Cache-Control是比较重要的 ...
- 【jvm】08-垃圾回收器那么多傻傻分不清?
[jvm]08-垃圾回收器那么多傻傻分不清? 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的理由!
序言 Spring Data JPA作为Spring Data中对于关系型数据库支持的一种框架技术,属于ORM的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度. 本文档隶属于< ...
随机推荐
- 图论——迪杰斯特拉算法(Dijkstra)实现,leetcode
迪杰斯特拉算法(Dijkstra):求一点到另外一点的最短距离 两种实现方法: 邻接矩阵,时间复杂度O(n^2) 邻接表+优先队列,时间复杂度O(mlogn)(适用于稀疏图) (n:图的节点数,m:图 ...
- 【QT】多个槽函数绑定同一个信号的触发顺序
目录 一.Qt 3.0(包含3.0) - Qt 4.5(包含4.5)版本之前 二.Qt 4.6(包含4.6)版本之后 一.Qt 3.0(包含3.0) - Qt 4.5(包含4.5)版本之前 「多个槽函 ...
- SQL:我为什么慢你心里没数吗?
SQL 语句执行慢的原因是面试中经常会被问到的,对于服务端开发来说也是必须要关注的问题. 在生产环境中,SQL 执行慢是很严重的事件.那么如何定位慢 SQL.慢的原因及如何防患于未然.接下来带着这些问 ...
- 配置redis服务器允许远程连接
说明 默认情况下,redis只允许本机访问.如果需要外部访问,需要修改下配置文件. 配置修改 redis.windows.conf 将bind 127.0.0.1 注释 将protected-mode ...
- 深入浅出 Git
开篇 你可能遇到过 如果你遇到这个场景,那你可能需要版本控制. 什么是版本控制 版本控制最主要的功能就是追踪文件的变更.它将什么时候.什么人更改了文件的什么内容等信息忠实地了已录下来.每一次文件的改变 ...
- Json串的字段如果和类中字段不一致,如何映射、转换?
Json串是我们现在经常会遇到的一种描述对象的字符串格式.在用Java语言开发的功能中,也经常需要做Json串与Java对象之间的转换. fastjson就是经常用来做Json串与Java对象之间的转 ...
- java文本获取
public static String Html2Text(String inputString) { String htmlStr = inputString; // 含html标 ...
- MM-合作伙伴确定过程
第一步:物料管理---采购---合作伙伴确定---合作伙伴角色---定义合作伙伴角色. 第二步:物料管理---采购---合作伙伴确定---合作伙伴角色---定义每个科目组适合的合作伙伴角色. 第三步: ...
- Shiro认证详解
Shiro shiro是一个java的安全框架 官网地址 http://shiro.apache.org/ 目录 Shiro Shiro综述 过滤器 注解 整合Shiro 1. 配置SecurityM ...
- Redis基础篇(六)数据同步:主从复制
Redis具有高可靠性,体现在两方面: 一是数据尽量少丢失,通过前面介绍的持久化方式AOF和RDB,在宕机时可以恢复数据. 二是服务尽量少中断,通过副本冗余来实现. 今天我们学习的就是通过主从复制实现 ...