C#中的foreach语句可用于循环遍历某个集合中的元素,而所有的只要支持了IEnumerable或IEnumerable<T>泛型接口的类型都是可以

用foreach遍历的。其具体的遍历实现过程就是利用C#中的迭代器中的方法来按照特定顺序遍历的。在.NET中IEnumerator和IEnumerator<T>

就是对迭代器的抽象,如果要自定义的类型也支持foreach循环则首先须要声明该类支持IEnumerable或IEnumerable<T>接口,然后再去实现自己

的支持了IEnumerator<T>的迭代器类型;唉,先看代码吧!

---------YYC

For Example:


//  实现了IEnumerable<T>泛型接口的类

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Pra6
{
public enum PhoneType
{
家庭电话,办公电话,手机,小灵通,传真
} class Phones : IEnumerable<string>
{
private string[] phones;
private int count = 0;
public int Count {
get { return count; }
}
public string this[PhoneType type]
{
get {
return phones[(int)type];
}
set {
int index = (int)type;
if (phones[index] == null && value != null)
{
count++;
}
else
if (phones[index] != null && value == null)
{
count--;
}
phones[index] = value;
}
} public Phones()
{
phones = new string[5];
}
public void CopyTo( Array array,int index)
{
foreach(string s in phones )
{
if (s != null)
array.SetValue(s,index++);
}
}
public IEnumerator<string > GetEnumerator()//返回迭代器
{
return new MyEnumerator<string>(phones);
}
IEnumerator IEnumerable.GetEnumerator()//返回迭代器,由于IEnumerable<T>接口也继承了IEnumerable接口所以出于兼容性考虑,最后也要实现该方法,但内容可//以和上面的代码一样
{
return this.GetEnumerator();
} }
}


//  实现了IEnumerator<T>的迭代器类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace Pra6
{
class MyEnumerator<T>:IEnumerator<T>
{
private int current;
internal T[] array;
public T Current {//返回当前数据
get { return array[current]; }
}
public MyEnumerator(T[] array)
{
this.array = array;
this.current = -1;
}
public bool MoveNext()//使迭代器移向下一项
{
if (++current == array.Length)
return false ;
return true;
}
object IEnumerator.Current//返回当前的数据,同样也是出于兼容性的考虑
{
get { return array [current];}
}
public void Reset()//重设迭代器,以便重新开始遍历
{
current = -1;
}
void IDisposable.Dispose()
{ } }
}

//调用过程

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace Pra6
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
LinkedList<string> aa = new LinkedList<string>();
string a1 = "aa";
string a2 = "bb";
string a3 = "cc";
string a4 = "dd";
LinkedListNode<string> b1 = aa.AddFirst(a1);
b1 = aa.AddAfter(b1,a2);
b1 = aa.AddAfter(b1, a3);
aa.AddLast(a4);
textBox1.Text = null ;
foreach (string a in aa )
{
textBox1.Text += " " + a;
}
b1 = b1.Next;
b1 = b1.Next; textBox1.Text += b1.Value; } private void textBox1_TextChanged(object sender, EventArgs e)
{ } private void button2_Click(object sender, EventArgs e)
{
Phones ph = new Phones();
ph[PhoneType.办公电话] = "111";
ph[PhoneType.传真] = "222";
ph[PhoneType.家庭电话] = "333";
ph[PhoneType.手机] = "444";
ph[PhoneType.小灵通] = "555";
textBox1.Text = null;
//方法一:调用foreach实现
foreach(string s in ph)
{
textBox1.Text += s+" ";
} //调用迭代器实现遍历。
IEnumerator<string> iter = ph.GetEnumerator();
while(iter.MoveNext())
{
textBox1.Text += iter.Current + " ";
}
}
}
}

其实,在.NET的中间语言是并不支持foreach语句的,而是C#的编译器可以将程序中的foreach语句转换成

对迭代器操作的while或for语句的循环遍历,例如:上面的:

foreach(string s in ph)
            {
                textBox1.Text += s+"   ";
            }

其真实的执行代码就是

IEnumerator<string> iter = ph.GetEnumerator();
            while(iter.MoveNext())
            {
                textBox1.Text += iter.Current + "   ";
            }

所以当我们懂了这个实现原理后我们也是可以去定义我们自己的可以支持foreach的类型了,

但是需要值得一提的是并非我们每次都需要去显示的自己定义我们的迭代器类型,C#语言本身

一大特色就是快速开发吗,这是因为C#中为迭代器模式提供了一种简化实现方式,即使用yield returne语句。

例如:将上面的Phones类中的GetEnumerator()直接改为下面的方式,不用再去定义迭代器类型,就能直接

使用foreach语句:

public IEnumerator<string> GetEnumerator()
{
for (int i = 0; i < 5;i++ )
{
if (phones[i]!=null)
yield return phones[i];
}
}






												

C#中foreach语句的迭代器实现机制的更多相关文章

  1. C#基础知识---迭代器与Foreach语句

    一.Foreach语句简介 在C# 1.0中我们经常使用foreach来遍历一个集合中的元素,然而如果一个集合要支持使用foreach语句来进行遍历,这个集合一般需要IEnumerable或IEnum ...

  2. Java中的可变参数以及foreach语句

    Java中的可变参数的定义格式如下: 返回值类型  方法名称(类型 ... 参数名称){} foreach语句的格式如下: for ( 数据类型  变量名称 :数据名称){ ... } public ...

  3. C#中的foreach语句与枚举器接口(IEnumerator)及其泛型 相关问题

    这个问题从<C#高级编程>数组一节中的foreach语句(6.7.2)发现的. 因为示例代码与之前的章节连贯,所以我修改了一下,把自定义类型改为了int int[] bs = { 2, 3 ...

  4. 【Java学习笔记之十】Java中循环语句foreach使用总结及foreach写法失效的问题

    foreach语句使用总结 增强for(part1:part2){part3}; part2中是一个数组对象,或者是带有泛性的集合. part1定义了一个局部变量,这个局部变量的类型与part2中的对 ...

  5. PHP:第二章——PHP中的foreach语句

    foreach语句提供了遍历数组的 <?php header("Content-Type:text/html;charset=utf-8"); $arr=array(&quo ...

  6. 浅析foreach语句

    本篇是我对于foreach语句(增强for)的总结: 我的总结流程如下: 1.先整体说明增强for遍历集合与数组之间的区别. 2.通过一维数组来说明(给出反编译的源码,形成对照). 3.通过二维数组来 ...

  7. foreach语句的用法

    foreach语句: foreach语句是for语句的特殊简化版本,不能完全取代for语句,但任何foreach语句都可以改写为for语句版本.foreach并不是一个关键字,习惯上将这种特殊的for ...

  8. 编写高质量代码改善C#程序的157个建议——建议30:使用LINQ取代集合中的比较器和迭代器

    建议30:使用LINQ取代集合中的比较器和迭代器 LINQ提供了类似于SQL的语法来实现遍历.筛选与投影集合的功能. static void Main(string[] args) { List< ...

  9. 6.2 C# 2:利用 yield 语句简化迭代器

    class Program { static void Main(string[] args) { object[] values = new object[] { "a", &q ...

随机推荐

  1. Android实现获取应用程序相关信息列表的方法

    本文所述为Androdi获取手机应用列表的方法,比如获取到Android应用的软件属性.大小和应用程序路径.应用名称等,获取所有已安装的Android应用列表,包括那些卸载了的,但没有清除数据的应用程 ...

  2. opencv-python 学习笔记1:简单的图片处理

    一.主要函数 1. cv2.imread():读入图片,共两个参数,第一个参数为要读入的图片文件名,第二个参数为如何读取图片,包括cv2.IMREAD_COLOR:读入一副彩色图片:cv2.IMREA ...

  3. 传智播客C/C++各种开发环境搭建视频工具文档免费教程

    传智播客作为中国IT培训的领军品牌,一直把握技术趋势,给大家带来最新的技术分享!传智播客C/C++主流开发环境免费分享视频文档中,就有写一个helloworld程序的示范.火速前来下载吧 所谓&quo ...

  4. HDU 5726 GCD(DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5726 [题目大意] 给出数列An,对于询问的区间[L,R],求出区间内数的GCD值,并且求出GCD ...

  5. Reorder the Books(规律)

    Reorder the Books Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  6. bzoj 1042: [HAOI2008]硬币购物 dp+容斥原理

    题目链接 1042: [HAOI2008]硬币购物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1706  Solved: 985[Submit][ ...

  7. tomcat远程debug端口开启

    declare -x CATALINA_OPTS="-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt ...

  8. web乱码问题

    String data = "不见青山"; ServletOutputStream sos = response.getOutputStream(); byte b[] = dat ...

  9. 基于MAVEN的SSM+ehcache+c3p0

    目录结构: 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http ...

  10. ASP.NET 使用My97DatePicker日期控件

    首先要下载该控件的包,下载地址:http://pan.baidu.com/s/1Aa5gk 引用文件 <script src="js/My97DatePicker/WdatePicke ...