什么是Enumerable

  • 在一些返回集合数据的接口中,我们经常能看到IEnumerable接口的身影。那什么是Enumerable呢?首先它跟C#中的enum关键字所表达的意思是不同的, 从翻译上来看:可枚举的,展开来说就是它的数据是一枚一枚可以让我们列举出来。就像人们排队去打疫苗,排队的人就是可枚举的,他们有的开车,有走着,有早有晚全都按照先来后到的顺序排好队,当医生开始进行打疫苗的工作时,他并不关心有多少人在排队,也不关心是否有人迟到,当然也不能越过第一个人让其后边的人先进来打,他只能说“请下一个人进来打疫苗”,如果没人响应医生就等着,直到有人进来开始接种,当前这个人完成接种后,医生继续叫下一个人,直到所有人都打完疫苗。这样的情景在编程中就体现为对Enumerable数据的操作。

接口成员及使用示例

我们先来看接口中有什么,因为IEnumerable接口一般都是用其泛型版,我们直接看这种:

Enumerable - 图1

  • 接口内容很简单,但是其中又出现了一个名为IEnumerator的接口,我们可以称之为枚举器,再来看看IEnumerator内部成员:

Enumerable - 图2 Enumerable - 图3

  • IEnumerator接口有三个成员,Current就是保存的当前数据对象,MoveNext方法则是将指针指向下个对象(类似打疫苗情景中的”下一位”),Reset则是将指针复位,泛型版接口则对其内部名为Current的成员指定了类型。也就是说通过枚举我们可以获取一个枚举器,通过枚举器我们能找到一个个数据对象,明白了这一点,我们就能大体上了解如何通过IEnumerable来获取数据了,那下面请看代码: Enumerable - 图4

  • 代码中有一个返回IEnumerable<string>的方法,用来模拟数据的产生,其中用到了一个yield关键字,我简单来说yield return就是部分返回(产生了一个数据,就返回一个,yield具体用法请看我上一篇分享的文章:[C#.NET 拾遗补漏] 理解 yield 关键字),这个方法最终的运行效果就是一秒钟返回一个当前时间构成一个IEnumerable<string>集合。

  • foreach就是为遍历IEnumerable数据打造的,它里边为我们封装了访问枚举器的操作,所以我们用它来遍历数据非常方便,下面来看一下运行效果: Enumerable - 图5

  • 当然,我们也想知道不用foreach应该怎么遍历IEnumerable数据,所以请看如下代码: Enumerable - 图6

  • 拿到枚举器,我们就可以调用MoveNext找数据(为什么要先调用MoveNext,而不是先取值,再调用MoveNext寻找下一个数据,大家可以再次联想一下打疫苗的情景:是先叫人,人到了,才能打疫苗),该方法返回bool值,有数据可寻则返回true,无数据则返回false,这就是循环的关键,运行结果跟上图一致,此处不再展示。