C#语言学习笔记8 —— yield 语句的深入理解

C#语言学习笔记8 —— yield 语句的深入理解

编码文章call10242025-02-11 11:31:438A+A-

yield 语句的深入理解

要理解 yield 语句,首先要了解 .Net 的迭代器(iterator)。

在计算机内存里,数据往往是按一定数据结构存储的。

.Net框架提供了许多常见的结构,比如 List、Dictionary、Stack、ObservableCollection、ConcurrentStack等等。

这些结构称为集合(collection),是容器(container)的一部分。collection 常按一定顺序来访问其元素,此时也称为序列(sequence)。

iterator 是一个对象,用来遍历 collection 中的元素。

具体的,iterator 就是 IEnumerable 和 IEnumerator 等接口的实例。

IEnumerable 和 IEnumerator 接口是与之对应的弱类型版本,它们的元素类型为 object。

IAsyncEnumerable 和 IAsyncEnumerator 接口是与之对应的异步版本,用于异步场景。


IEnumerable 接口定义

public interface IEnumerable : System.Collections.IEnumerable

方法 public
System.Collections.Generic.IEnumerator GetEnumerator ()

返回 enumerator 用来遍历 collection


IEnumerator 接口定义

public interface IEnumerator : IDisposable, System.Collections.IEnumerator

属性 public T Current { get; }

返回 collection 中 enumerator 当前位置的元素


IEnumerable 接口定义

public interface IEnumerable

方法 public
System.Collections.IEnumerator GetEnumerator ()

返回 enumerator 用来遍历 collection


IEnumerator 接口定义

public interface IEnumerator

属性 public object Current { get; }

返回 collection 中 enumerator 当前位置的元素

方法 public bool MoveNext ()

把 enumerator 推进到 collection 的下一个元素,成功推进返回true,越过 collection 的尾端返回false

方法 public void Reset ()

把 enumerator 的初始位置,即第一个元素之前的位置。


foreach 语句的执行

请看下面这个 foreach 语句的例子,其中 collection 的类型为 IEnumerable

编译器产生的代码大概是这样子

下面是自定义实现一个 IEnumerable 的例子,用于生成一个质数序列。

首先是 PrimeNumberGenerator 类,它实现 IEnumerable 接口。

其次是 PrimeNumberEnumerator 类,它实现 IEnumerator 接口。 PrimeNumberGenerator 类引用 PrimeNumberEnumerator 类。

使用 PrimeNumberGenerator 类的演示代码片段

改为使用 yield 语句来实现,取代前面的 PrimeNumberGenerator 类和 PrimeNumberEnumerator 类。

是不是很简单明了?运行结果完全一样。

使用 dotPeek 工具来反编译上面使用了 yield 语句的 GetPrimeNumbers 方法,其底层实现代码如下所示


由反编译的代码可以看出,编译器自动生成了一个类, 帮你实现了IEnumerable、 IEnumerator、 IEnumerable、IEnumerator、IDisposable 等接口。

相比手工实现要编写一大堆固定模式、复杂易错的代码,yield 语句确实带来了很多方便。

而且,要特别地注意到,在上面的例子中,当调用 GetPrimeNumbers 时,质数序列的元素此时并没有产生,它只是创建了一个类实例。 只有在 foreach 语句执行过程中,不断调用接口的 MoveNext 方法和 Current 属性,序列元素才会被产生和访问, 一个接一个地进行。

使用 yield 语句的方法称为迭代器方法,它们的执行过程都是这样的。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4