IEnumeratorIEnumerable这两个接口单词相近、含义相关,傻傻分不清楚。

入行多年,一直没有系统性梳理这对李逵李鬼。

最近本人在怼着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,你就不能将IEnumerableGetEnumerator方法的返回值转换为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`还傻傻分不清楚?的更多相关文章

  1. JS魔法堂:属性、特性,傻傻分不清楚

    一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...

  2. Java:接口和抽象类,傻傻分不清楚?

    01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...

  3. [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!

    十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...

  4. 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】

    文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...

  5. 傻傻分不清之 Cookie、Session、Token、JWT

    傻傻分不清之 Cookie.Session.Token.JWT 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打 ...

  6. Shell中傻傻分不清楚的TOP3

    Shell中傻傻分不清楚的TOP3 发布文章 近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Comm ...

  7. URI与URL傻傻分不清楚?

    前言 总所周知,缓存是解决Http1.1协议传输性能的问题中最主要的手段. 缓存既可以存在于浏览器上,也可以存在于服务器中. 而影响缓存的Http头部有很多,其中Cache-Control是比较重要的 ...

  8. 【jvm】08-垃圾回收器那么多傻傻分不清?

    [jvm]08-垃圾回收器那么多傻傻分不清? 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...

  9. JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的理由!

    序言 Spring Data JPA作为Spring Data中对于关系型数据库支持的一种框架技术,属于ORM的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度. 本文档隶属于< ...

随机推荐

  1. C#声明一个100大小的数组 随机生成1-100之间不重复的数

    面试题:C#声明一个100大小的数组 随机生成1-100之间不重复的数下面是C#的实现方式,编译测试通过 public static void InsertRandomArray() { int[] ...

  2. js原生方法filter实现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Kruskal重构树——[NOI2018] 归程

    题目链接: UOJ LOJ 感觉 Kruskal 重构树比较简单,就不单独开学习笔记了. Statement 给定一个 \(n\) 点 \(m\) 边的无向连通图,用 \(l,a\) 描述一条边的长度 ...

  4. NOI Online 题解

    T1 对\(t_i = 1\)的边,将\(u_i, v_i\)连一条边权为\(1\)的边.否则连一条边权为\(0\)的边. 对于每一个连通块,若图中不存在一条边权之和为奇数的圈,则可以将这个连通块二染 ...

  5. ant design 中实现表格头部可删除和添加

    我是用antd pro做一个项目.有一个小需求是表格头部栏可操作.具体是表头的每一项都带一个"x"按钮,当不想展示这一栏的时候,直接点"x",这一栏就不展示了. ...

  6. 死磕以太坊源码分析之Ethash共识算法

    死磕以太坊源码分析之Ethash共识算法 代码分支:https://github.com/ethereum/go-ethereum/tree/v1.9.9 引言 目前以太坊中有两个共识算法的实现:cl ...

  7. css 06-CSS盒模型详解

    06-CSS盒模型详解 #盒子模型 #前言 盒子模型,英文即box model.无论是div.span.还是a都是盒子. 但是,图片.表单元素一律看作是文本,它们并不是盒子.这个很好理解,比如说,一张 ...

  8. 1-解决java Scanner出现 java.util.NoSuchElementException

    起因:在函数中新建scanner对象,然后多次调用此方法出现上述异常 原因:Scanner(system.in)在Scanner中接受的是键盘 输入,当调用close()方法时 Scanner的关闭会 ...

  9. 7. 丈母娘嫌我不懂K8s的Service概念,让我去面壁

    文章目录 怎么跟你说 Service的出现,就是 解决ip不固定的问题 ,怎么解决呢 ? 听小刘慢慢道来 当Pod宕机后重新生成时,其IP等状态信息可能会变动,Service会根据Pod的Label对 ...

  10. Elasticsearch 学习二(请求流程).

    一.写入数据 1.ES 的任意节点都可以作为协调(Coordinating)节点接受请求(包括新建.索引或者删除请求),每个节点都知道集群中任一文档位置: 2.协调节点会通过 routing 字段计算 ...