1:枚举器和可枚举类型

我们知道使用foreach可以遍历数组中的元素。那么为什么数组可以被foreach语句处理呢,下面我们就进行讨论一下这个问题。

2:使用foreach语句

我们知道当我们使用foreach语句的时候,这个语句为我们依次取出了数组中的每一个元素。

例如下面的代码:

             int[] arr = { , , , , ,  };
foreach( int arry in arr )
{
Console.WriteLine("Array Value::{0}",arry);
}

输出效果为

为什么数组可以使用foreach来遍历,原因是数组可以按需提供一个叫做枚举器(enumerator)的对象,枚举器可以依次返回请求的数组中的元素,枚举器知道项的次序并且跟踪它在序列中的位置。依次返回请求的当前项。

  对于有枚举器的类型而言,必须有一个方法来获取它这个类型。获取一个对象枚举器的方法是调用对象的GetEnumrator方法,实现GetEnumrator方法的类型叫做可枚举类型。那么数组就是可枚举类型。

  下图演示一下可枚举类型和枚举器之间的关系。

foreach结构设计用来和可枚举类型一起使用,只要给它的遍历对象是可枚举类型,比如数组。

1:通过调用GetEnumrator方法获取对象的枚举器。

2:从枚举器中请求每一项并且把它作为迭代器,代码可以读取该变量,但不可以改变

foreach(Type VarName in EnumrableObject )

{

  ...

}

EnumrableObjec必须是可枚举类型。

2:IEnumrator接口

IEnumrator接口包含了3个函数成员:Current、MoveNext以及Reset;

.Current是返回序列中当前位置项的属性。(注意:Current它是只读属性,它返回Object类型的引用,所以可以返回任意类型)

.MoveNext是把枚举器位置前进到集合中下一项的方法。它也但会布尔值,指示新的位置是否是有效位置。

注:如果返回的位置是有效的,方法返回true;

  如果新的位置是无效的,方法返回false;

  枚举器的原始位置在序列中的第一项之前,因此MoveNext必须在第一次使用Current之前调用。

.Reset是把位置重置为原始状态的方法。

下面我们用图表示一下他们之间的关系

有了集合的枚举器,我们就可以使用MoveNext和Current成员来模仿foreach循环遍历集合中的项,例如,我们已经知道数组是可枚举类型,所以下面的代码手动做foreach语句

自动做的事情。

代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] arr = { , , , , , };
IEnumerator ie = arr.GetEnumerator();
while( ie.MoveNext() )
{
int i = (int)ie.Current;
Console.WriteLine("{0}", i);
}
}
}
}

程序运行的结果为

我们来用图解释一下代码中的数组结构

IEnumerable接口

数组是可枚举类型,是因为实现了IEnumerable接口的类,所以可枚举类都是因为实现了IEnumerable接口的类。

IEnumerable接口只有一个成员——GetEnumerator()方法,它返回对象的枚举器。

如图所示:

下面我们举一个使用IEnumerator和IEnumerable的例子

下面的代码展示了一个可枚举类的完整示例,该类叫Component(球形)。它的枚举器类为Shape(形状)。

代码如下:

 using System;
using System.Collections; namespace ConsoleApplication1
{
class Shape : IEnumerator
{
string[] _Shapes;
int _Position = -; public Shape(string[] _theShapes)
{
_Shapes = new string[_theShapes.Length];
for( int i = ; i < _theShapes.Length; i++ )
{
_Shapes[i] = _theShapes[i];
}
} public Object Current
{
get
{
if ( _Position == - )
throw new InvalidOperationException();
if (_Position >= _Shapes.Length)
throw new InvalidOperationException();
return _Shapes[_Position];
}
} public bool MoveNext()
{
if (_Position < _Shapes.Length - )
{
_Position++;
return true;
}
else
return false;
} public void Reset()
{
_Position = -;
}
} class Component : IEnumerable
{
string[] shapes = { "Circular", "spherical", "Quadrilateral", "Label" };
public IEnumerator GetEnumerator()
{
return new Shape( shapes );
}
} class Program
{
static void Main(string[] args)
{
Component comp = new Component();
foreach ( string oshape in comp )
Console.WriteLine(oshape);
} }
}

运行结果:

如果您看了本篇博客,觉得对您有所收获,请点击右下角的 [推荐]

如果您想转载本博客,请注明出处

如果您对本文有意见或者建议,欢迎留言

感谢您的阅读,请关注我的后续博客

C# 枚举器的更多相关文章

  1. for..in遍历,枚举器

    #pragma mark ------------for循环遍历集合中的元素------ //创建一个数组,包含5个字符串对象,倒序取出数组中的所有元素,并存储到另一可变数组中 NSArray *ar ...

  2. ruby迭代器枚举器

    迭代器一个迭代器是一个方法,这个方法里面有yield语句,使用了yield的方法叫做迭代器,迭代器并非一定要迭代,与传递给这个方法的块进行数据传输 yield将数据传给代码快,代码块再把数据传输给yi ...

  3. ruby中迭代器枚举器的理解

    参考<ruby编程语言>5.3迭代器和可枚举对象 迭代器一个迭代器是一个方法,这个方法里面有yield语句,这个方法里的yield语句,与传递给这个方法的块进行数据传输 yield将数据传 ...

  4. JAVA中的数据结构——集合类(序):枚举器、拷贝、集合类的排序

    枚举器与数据操作 1)枚举器为我们提供了访问集合的方法,而且解决了访问对象的“数据类型不确定”的难题.这是面向对象“多态”思想的应用.其实是通过抽象不同集合对象的共同代码,将相同的功能代码封装到了枚举 ...

  5. ruby迭代器iterator和枚举器Enumerator

    编写自定义的迭代器 The defining feature of an iterator method is that it invokes a block of code associatedwi ...

  6. C#中的枚举器(转)

    术语表 Iterator:枚举器(迭代器) 如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.这在C# 2.0中比 C# 1.1更容 ...

  7. C#枚举器接口IEnumerator的实现

    原文(http://blog.csdn.net/phpxin123/article/details/7897226) 在C#中,如果一个类要使用foreach结构来实现迭代,就必须实现IEnumera ...

  8. c# foreach枚举器

    要是自己的类支持foreach ,必须在类中必须有GetEnumerator方法,该方法返回的是一个IEnumerator类型的枚举器; public class MyStruct { public ...

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

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

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

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

随机推荐

  1. 关于input内容改变的触发时间

    1.onchange onchange 事件会在域的内容改变时触发.支持的标签<input type="text">, <textarea>, <se ...

  2. TensorFlow拟合线性函数

    TensorFlow拟合线性函数 简单的TensorFlow图构造 以单个神经元为例 x_data数据为20个随机 [0, 1) 的32位浮点数按照 shape=[20] 组成的张量 y_data为 ...

  3. 通过cmd命令行连接mysql数据库

    找到 mysqld.exe所在的路径 使用cd切换到msyqld.exe路径下 输入mysql连接命令,格式如下 Mysql  -P 端口号  -h  mysql主机名\ip -u root (用户) ...

  4. Alpha第六天

    Alpha第六天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  5. 敏捷冲刺每日报告——Day1

    1.情况简述 Alpha阶段第一次Scrum Meeting 敏捷开发起止时间 2017.10.25 00:00 -- 2017.10.26 00:00 讨论时间地点 2017.10.25晚9:30, ...

  6. Linux进程调度分析

    原文:http://www.2cto.com/os/201112/113229.html 操作系统要实现多进程,进程调度必不可少. 有人说,进程调度是操作系统中最为重要的一个部分.我觉得这种说法说得太 ...

  7. 使用HttpClient4.5实现HTTPS的双向认证

    说明:本文主要是在平时接口对接开发中遇到的为保证传输安全的情况特要求使用https进行交互的情况下,使用httpClient4.5版本对HTTPS的双向验证的  功能的实现    首先,老生常谈,文章 ...

  8. nyoj 回文字符串

    回文字符串 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba".当 ...

  9. zookeeper入门系列:paxos协议

    上一章讨论了一种强一致性的情况,即需要分布式事务来解决,本章我们来讨论一种最终一致的算法,paxos算法. paxos算法是由大牛lamport发明的,关于paxos算法有很多趣事.比如lamport ...

  10. OpenGL中怎么把世界坐标系变成屏幕坐标系

    对这个3D坐标手动进行OpenGL的四个变换,得到的结果就是屏幕上的像素坐标.前三个变换(Model, View, Projection)都是4x4矩阵,操作对象是四维向量,所以需要把(100, 10 ...