C#中迭代器的概念和两种实现方式
1.首先我们看下IEnumerable接口定义:
namespace System.Collections
{
// Summary:
// Exposes the enumerator, which supports a simple iteration over a non-generic
// collection.
[ComVisible(true)]
[Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
public interface IEnumerable
{
// Summary:
// Returns an enumerator that iterates through a collection.
//
// Returns:
// An System.Collections.IEnumerator object that can be used to iterate through
// the collection.
[DispId(-4)]
IEnumerator GetEnumerator();
}
}
这个接口是重中之重,迭代器就是实现这个接口才能使之迭代的。
2.C#的yield关键字您也必须知道
yield在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它有两种表现形式:
yield return <expression>;
yield break;
请注意:
expression 必须可以隐式转换为迭代器的 yield 类型
yield语句只能主线在迭代模块中,而不能出现在不安全模块,也不能出现在匿名方法中;当和 expression 一起使用时,yield return 语句不能出现在 catch 块中或含有一个或多个 catch 子句的 try 块中。
3.介绍迭代器概念
其实所谓迭代就是指循环,迭代器是指实现该循环的一种方式。
迭代器是C#2.0增加的功能,它可以是方法、get访问器或运算符,最终它可以使您能够在类或结构中支持foreach迭代。在实现上您不必实现整个IEnumerable接口,您只需提供一个迭代器即可,当编译器监测到迭代器时间,她会自动生成IEnumerable 或 IEnumerable<T> 接口的 Current、MoveNext 和 Dispose 方法。
迭代器是可以返回相同类型的值的有序序列的一段代码,它使用yield return语句一次返回每个元素,使用yield break终止迭代,它的返回类型必须是IEnumerable、 IEnumerator、IEnumerable<T> 或 IEnumerator<T>。
3.创建迭代器最常用的方法是实现IEnumerable接口中的GetEnumerator方法,IEnumerable接口如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ctochina.net
{
class Program
{
static void Main(string[] args)
{
MyIterator myIterator = new MyIterator();
foreach (int i in myIterator)
{
Console.WriteLine(i);
}
}
}
public class MyIterator
{
public IEnumerator GetEnumerator()
{
for(int i=1;i<8;i++)
{
yield return i;
}
}
}
}
输出:
1 2 3 4 5 6 7
注意System.Collections;命名空间的引用,因为IEnumerator在其中
由于是实现IEnumerable接口中的GetEnumerator方法,所以一个类中只能有一个GetEnumerator迭代。
4.另一种实现迭代的方法,代码接着上例如:
| using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace ctochina.net { class Program { static void Main(string[] args) { MyIterator myIterator = new MyIterator(); //迭代一 foreach (int i in myIterator) { Console.Write(i+"\t"); } Console.WriteLine(); //迭代二 foreach (int i in myIterator.MyEnumerator_instance(2,8)) { Console.Write(i + "\t"); } Console.WriteLine(); //迭代三 foreach (int i in MyIterator.MyEnumerator_static(2,8)) { Console.Write(i + "\t"); } } } public class MyIterator { //实现 IEnumerable 接口的 GetEnumerator 方法来实现迭代 public IEnumerator GetEnumerator() { for(int i=1;i<8;i++) { yield return i; } } //IEnumerable 的实例实现迭代 public IEnumerable MyEnumerator_instance(int iLoop, int jLoop) { for(;iLoop<=jLoop;iLoop++) { yield return iLoop; } } //IEnumerable 的静态实现迭代 public static IEnumerable MyEnumerator_static(int iLoop,int jLoop) { for (; iLoop <= jLoop; iLoop++) { yield return iLoop; } } } } |
输出:
1 2 3 4 5 6 7
2 3 4 5 6 7 8
2 3 4 5 6 7 8
可见这种方式灵活,一个类中可以有多个迭代的实现
C#中迭代器的概念和两种实现方式的更多相关文章
- Ajax中的get和post两种请求方式的异同
Ajax中我们经常用到get和post请求.那么什么时候用get请求,什么时候用post方式请求呢? 在做回答前我们首先要了解get和post的区别. 1. get是把参数数据队列加到提交表单的A ...
- Hibernate中双向多对多的两种配置方式
Hibernate中双向多对多的两种配置方式 1.建立多对多双向关联关系 package cn.happy.entitys; import java.util.HashSet; import java ...
- MyBatis中主键回填的两种实现方式
主键回填其实是一个非常常见的需求,特别是在数据添加的过程中,我们经常需要添加完数据之后,需要获取刚刚添加的数据 id,无论是 Jdbc 还是各种各样的数据库框架都对此提供了相关的支持,本文我就来和和大 ...
- 转:Ajax中的get和post两种请求方式的异同
1. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML ...
- IOC容器在web容器中初始化——(一)两种配置方式
参考文章http://blog.csdn.net/liuganggao/article/details/44083817,http://blog.csdn.net/u013185616/article ...
- Spring 详解(二)------- AOP关键概念以及两种实现方式
目录 1. AOP 关键词 2. AOP 的作用 3. AOP 的通知类型 4. 基于 xml 的配置方式 5. 基于注解的配置方式 6. 切面的优先级 7. 重用切点表达式 8. 两种方式的比较(摘 ...
- jenkins中slave节点连接的两种常用方式
我们在使用jenkins的时候,一般来说肯定是有slave节点的,本来网上也有好多关于jenkins节点配置的教程,我也就不写了.简单说明一下:任务一般是在slave上面运行的.当然不是讲master ...
- Android中BroadcastReceiver的两种注册方式(静态和动态)详解
今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...
- Android中Fragment与Activity之间的交互(两种实现方式)
(未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...
随机推荐
- Asp.net中防止用户多次登录的方法
在web开发时,有的系统要求同一个用户在同一时间只能登录一次,也就是如果一个用户已经登录了,在退出之前如果再次登录的话需要报错. 常见的处理方法是,在用户登录时,判断此用户是否已经在Applicati ...
- jQuery实现web页面固定列表搜索
1.需求分析:现在有一个数据展示列表页面,列表内容固定,使用jQuery在固定的列表中实现搜索功能. 2.核心代码: <!-- 添加jquery库 --> <script type= ...
- FPGA与PCI-E
从并行到串行: PCI Express(又称PCIe)是一种高性能.高带宽串行通讯互连标准,取代了基于总线的通信架构,如:PCI.PCI Extended (PCI-X) 以及加速图形端口(AGP). ...
- vim环境设置(应用于python编程)
1. 安装完整的vim # apt-get install vim-gnome 2. 安装ctags,ctags用于支持taglist,必需! # apt-get install ctags 3. 安 ...
- JS里try...catch...finally详解,以及console日志调试(console.log、console.info等)
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- 如何抽象一个 Vue 公共组件
之前一直想写一篇关于抽象 Vue 组件的随笔,无奈一直没想到好的例子.恰巧最近为公司项目做了一个数字键盘的组件,于是就以这个为例聊聊如何抽象 Vue 的组件. 先上 Demo 与 源码.(demo最好 ...
- win10 uwp 切换主题
本文主要说如何在UWP切换主题,并且如何制作主题. 一般我们的应用都要有多种颜色,一种是正常的白天颜色,一种是晚上的黑夜颜色,还需要一种辅助的高对比颜色.这是微软建议的,一般应用都要包含的颜色. 我们 ...
- UVa11882,Biggest Number
搜索+剪枝 如此水的一个题,居然搞了一上午 出错在bfs与dfs时共用了一个vis数组,导致bfs完后返回dfs应该能访问到的点访问不到 自己想怎么剪枝,想了几个剪枝方法,又证明,又推翻,再想,再证明 ...
- centos安装SWFtools服务(pdf2swf)
第一步:下载swftools-0.9.2.tar.gz 第二步:swftools tar -xzvf swftools-0.9.2.tar.gz cd swftools-0.9.2 ./configu ...
- onclick事件触发 input type=“file” 上传文件
添加按钮: <input type="button" name="button" value="浏览" onclick="j ...