迭代器模式是设计模式的一种,因为其运用的普遍性,很多语言都有内嵌的原生支持

在.NET中,迭代器模式是通过IEnumeratorIEnumerable两个接口(有非泛型和泛型2种版本)来封装的

迭代器模式的一个重要方面是:不是一次返回所有数据,而是每次调用只返回一个元素

Array、IEnumerable和IEnumerator之间关系如下:

foreach遍历

① Array、集合容器类派生于IEnumerable接口类(该类中含有一个IEnumerator GetEnumerator()接口函数),Array、集合容器类实现了该函数,这使得foreach可对其进行遍历

注:不需要从IEnumerable派生,只要类实现了IEnumerator GetEnumerator()函数,就可以使用foreach遍历该类中的元素

② IEnumerator定义了Current属性来返回游标所在的元素,MoveNext方法移动到下一个元素(若有元素则返回true,若到达末尾则返回false),Reset方法是将游标重置到第一项的位置

int[] IntArray = new int[] { , ,  };

foreach (int n in IntArray)
{
Console.WriteLine(n);
} // 上面的foreach等价于下方的代码实现
IEnumerator e = IntArray.GetEnumerator();
try
{
while (e.MoveNext())
{
Console.WriteLine((int)e.Current);
}
}
finally
{
var disposable = e as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

在C#1.0中,创建IEnumerator枚举器需要写大量的代码。C#2.0添加了yield语句,让编译器自动创建IEnumerator枚举器。

yield return语句返回集合的一个元素,并移动到下一个元素上。yield break可停止迭代。

非泛型版本IEnumerator

class EnumeratorTest
{
public IEnumerator GetEnumerator()
{
yield return ;
yield return "Good";
}
} EnumeratorTest eTest = new EnumeratorTest();
foreach (object o in eTest)
{
Console.WriteLine(o);
}

编译后生成的代码如下:

class EnumeratorTest
{
public IEnumerator GetEnumerator()
{
return new GenerateEnumerator();
} private sealed class GenerateEnumerator : IEnumerator<object>, IEnumerator, IDisposable
{
// Fields
private int state;
private object current; // Methods
public GenerateEnumerator(int state)
{
this.state = state;
} bool IEnumerator.MoveNext()
{
switch (this.state)
{
case :
this.state = -;
this.current = ;
this.state = ;
return true; case :
this.state = -;
this.current = "Good";
this.state = ;
return true; case :
this.state = -;
break;
}
return false;
} void IEnumerator.Reset()
{
throw new NotSupportedException();
} void IDisposable.Dispose()
{
} // Properties
object IEnumerator<object>.Current
{
get
{
return this.current;
}
}
object IEnumerator.Current
{
get
{
return this.current;
}
}
}
} EnumeratorTest eTest = new EnumeratorTest();
IEnumerator e = eTest.GetEnumerator();
try
{
while (e.MoveNext())
{
Console.WriteLine(e.Current);
}
}
finally
{
var disposable = e as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

泛型版本IEnumerator<T>

class EnumeratorTest2
{
private bool m_bBreak; public EnumeratorTest2(bool bBreak)
{
m_bBreak = bBreak;
} public IEnumerator<string> GetEnumerator()
{
yield return "Hello";
if (m_bBreak)
{
yield break;
}
yield return "World";
}
} EnumeratorTest2 eTest2 = new EnumeratorTest2(true);
IEnumerator<string> e2 = eTest2.GetEnumerator();
while (e2.MoveNext())
{
Console.WriteLine(e2.Current);
}

编译后生成的代码如下:

class EnumeratorTest2
{
private bool m_bBreak; public EnumeratorTest2(bool bBreak)
{
m_bBreak = bBreak;
} public IEnumerator<string> GetEnumerator()
{
GenerateEnumerator2 e2 = new GenerateEnumerator2();
e2.eTest2 = this;
return e2;
} private sealed class GenerateEnumerator2 : IEnumerator<string>, IEnumerator, IDisposable
{
// Fields
private int state;
private string current; public EnumeratorTest2 eTest2; // Methods
public GenerateEnumerator2(int state)
{
this.state = state;
} bool IEnumerator.MoveNext()
{
switch (this.state)
{
case :
this.state = -;
this.current = "Hello";
this.state = ;
return true; case :
this.state = -;
if (eTest2.m_bBreak)
{
break;
}
this.current = "World";
this.state = ;
return true; case :
this.state = -;
break;
}
return false;
} void IEnumerator.Reset()
{
throw new NotSupportedException();
} void IDisposable.Dispose()
{
} // Properties
string IEnumerator<string>.Current
{
get
{
return this.current;
}
}
object IEnumerator.Current
{
get
{
return this.current;
}
}
}
} EnumeratorTest2 eTest2 = new EnumeratorTest2(true);
IEnumerator<string> e2 = eTest2.GetEnumerator();
while (e2.MoveNext())
{
Console.WriteLine(e2.Current);
}

非泛型版本IEnumerable

class EnumeratorTest3
{
public IEnumerable Test1()
{
yield return ;
yield return ;
}
} EnumeratorTest3 eTest3 = new EnumeratorTest3();
foreach (object o in eTest3.Test1())
{
Console.WriteLine(o);
}

编译后生成的代码如下:

class EnumeratorTest3
{
public IEnumerable Test1()
{
return new GenerateEnumerable3();
} private sealed class GenerateEnumerable3 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
{
// Fields
private int state;
private int current; // Methods
public GenerateEnumerable3(int state)
{
this.state = state;
} bool IEnumerator.MoveNext()
{
switch (this.state)
{
case :
this.state = -;
this.current = ;
this.state = ;
return true; case :
this.state = -;
this.current = ;
this.state = ;
return true; case :
this.state = -;
break;
}
return false;
} IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
return this;
} IEnumerator IEnumerable.GetEnumerator()
{
return this;
} void IEnumerator.Reset()
{
throw new NotSupportedException();
} void IDisposable.Dispose()
{
} // Properties
object IEnumerator<object>.Current
{
get
{
return this.current;
}
}
object IEnumerator.Current
{
get
{
return this.current;
}
}
}
} EnumeratorTest3 eTest3 = new EnumeratorTest3();
IEnumerator e3 = eTest3.Test1().GetEnumerator();
while (e3.MoveNext())
{
Console.WriteLine(e3.Current);
}

泛型版本IEnumerable<T>

class EnumeratorTest4
{
private bool m_bBreak; public EnumeratorTest4(bool bBreak)
{
m_bBreak = bBreak;
} public IEnumerable<float> Test1()
{
yield return 1.0f;
if (m_bBreak)
{
yield break;
}
yield return 3.0f;
}
} EnumeratorTest4 eTest4 = new EnumeratorTest4(true);
foreach (object o in eTest4.Test1())
{
Console.WriteLine(o);
}

编译后生成的代码如下:

class EnumeratorTest4
{
private bool m_bBreak; public EnumeratorTest4(bool bBreak)
{
m_bBreak = bBreak;
} public IEnumerable<float> Test1()
{
GenerateEnumerable4 e4 = new GenerateEnumerable4();
e4.eTest4 = this;
return e4;
} private sealed class GenerateEnumerable4 : IEnumerable<float>, IEnumerable, IEnumerator<float>, IEnumerator, IDisposable
{
// Fields
private int state;
private float current; public EnumeratorTest4 eTest4; // Methods
public GenerateEnumerable4(int state)
{
this.state = state;
} bool IEnumerator.MoveNext()
{
switch (this.state)
{
case :
this.state = -;
this.current = 1.0f;
this.state = ;
return true; case :
this.state = -;
if (this.eTest4.m_bBreak)
{
break;
}
this.current = 3.0f;
this.state = ;
return true; case :
this.state = -;
break;
}
return false;
} IEnumerator<float> IEnumerable<float>.GetEnumerator()
{
return this;
} IEnumerator IEnumerable.GetEnumerator()
{
return this;
} void IEnumerator.Reset()
{
throw new NotSupportedException();
} void IDisposable.Dispose()
{
} // Properties
float IEnumerator<float>.Current
{
get
{
return this.current;
}
}
object IEnumerator.Current
{
get
{
return this.current;
}
}
}
} EnumeratorTest4 eTest4 = new EnumeratorTest4(true);
IEnumerator<float> e4 = eTest4.Test1().GetEnumerator();
while (e4.MoveNext())
{
Console.WriteLine(e4.Current);
}

C# 迭代器与yield关键字的更多相关文章

  1. yield 关键字和迭代器

    一般使用方法     yield 关键字向编译器指示它所在的方法是迭代器块 在迭代器块中,yield 关键字与 return 关键字结合使用,向枚举器对象提供值. 这是一个返回值,例如,在 forea ...

  2. Python:容器、迭代对象、迭代器、生成器及yield关键字

            在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...

  3. C#使用yield关键字构建迭代器

    http://www.cnblogs.com/Huaran1chendu/p/4838536.html 以前,如果我们希望构建支持foreach枚举的自定义集合,只能实现IEnumerable接口(可 ...

  4. 使用yield关键字让自定义集合实现foreach遍历

    一般来说当我们创建自定义集合的时候为了让其能支持foreach遍历,就只能让其实现IEnumerable接口(可能还要实现IEnumerator接口) 但是我们也可以通过使用yield关键字构建的迭代 ...

  5. (转) Python Generators(生成器)——yield关键字

    http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...

  6. 转载yield关键字理解

    实现IEnumerable接口及理解yield关键字   [摘要]本文介绍实现IEnumerable接口及理解yield关键字,并讨论IEnumerable接口如何使得foreach语句可以使用. 本 ...

  7. C# 基础小知识之yield 关键字 语法糖

    原文地址:http://www.cnblogs.com/santian/p/4389675.html 对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味 ...

  8. Python之路:迭代器和yield生成器

    一.迭代器 对于Python 列表的 for 循环,他的内部原理:查看下一个元素是否存在,如果存在,则取出,如果不存在,则报异常 StopIteration.(python内部对异常已处理) 使用迭代 ...

  9. C#2.0中使用yield关键字简化枚举器的实现

    我们知道要使用foreach语句从客户端代码中调用迭代器,必需实现IEnumerable接口来公开枚举器,IEnumerable是用来公开枚举器的,它并不实现枚举器,要实现枚举器必需实现IEnumer ...

随机推荐

  1. WinForm 程序在系统托盘显示

    前言 有些程序在关闭或最小化的时候会隐藏在系统托盘中,双击或右击会重新显示,winform实现其功能很简单,这边就简单的介绍下. 实现 在winform实现托盘使用notifyIcon控件,如果加菜单 ...

  2. VM1059 bootstrap-table.min.js:7 Uncaught TypeError: Cannot read property 'classes' of undefined

    参考链接:https://blog.csdn.net/liuqianspq/article/details/81868283 1.阳光明媚的下午,我在写CRUD,让数据传到前端的时候,解析的时候报错了 ...

  3. VS2013(InstallShield2015LimitedEdition)打包程序详解

    VS2012没有自带打包工具,所以要先下载并安装一个打包工具.我采用微软提供的打包工具:  InstallShield2015LimitedEdition.下载地址:https://msdn.micr ...

  4. jakarta-oro-2.0.8.jar-----------JAVA FTP相关

    资源不好找,找到了就和大家分享一下! 链接:https://share.weiyun.com/51kBB0y 密码:2hcxcu

  5. 基于WEB的网上购物系统-ssh源码

    基于WEB的网上购物系统主要功能包括:前台用户登录退出.注册.在线购物.修改个人信息.后台商品管理等等.本系统结构如下:(1)商品浏览模块:        实现浏览最新商品        实现按商品名 ...

  6. HighChat动态绑定数据 数据后台绑定(四)

    后台绑定数据,直接返回json数据 IList<SummaryHour> adHourData = summarybll.FindList(str); List<, , , , , ...

  7. Oracle 11g 手工建库

    假设数据库软件已经安装好,现在没有图形界面无法用dbca安装数据库,那么用手工建库,数据库名为edw 创建目录 [oracle@localhost ~]$ mkdir -p /u01/app/orac ...

  8. sql server 安装出现需要sqlncli.msi文件,错误为 microsoft sql server 2012 native client

    在安装sql server 2017 时出现 弹框标题为  microsoft sql server 2012 native client  内容为需要sqlncli.msi文件 去本地目录找本身的那 ...

  9. liteos错误处理(十一)

    1. 概述 1.1 基本概念 错误处理指用户代码发生错误时,系统调用错误处理模块的接口函数,完成上报错误信息,并调用用户自己的钩子函数,进行特定的处理. 错误处理模块实现OS内部错误码记录功能.OS内 ...

  10. 很不错的python 机器学习资源

    http://www.cuijiahua.com/resource.html 曾看过的书,感觉一些很有用的学习资料,推荐给大家! Python基础: 网络教程推荐: 系统学习python3可以看廖雪峰 ...