C# 枚举器
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# 枚举器的更多相关文章
- for..in遍历,枚举器
#pragma mark ------------for循环遍历集合中的元素------ //创建一个数组,包含5个字符串对象,倒序取出数组中的所有元素,并存储到另一可变数组中 NSArray *ar ...
- ruby迭代器枚举器
迭代器一个迭代器是一个方法,这个方法里面有yield语句,使用了yield的方法叫做迭代器,迭代器并非一定要迭代,与传递给这个方法的块进行数据传输 yield将数据传给代码快,代码块再把数据传输给yi ...
- ruby中迭代器枚举器的理解
参考<ruby编程语言>5.3迭代器和可枚举对象 迭代器一个迭代器是一个方法,这个方法里面有yield语句,这个方法里的yield语句,与传递给这个方法的块进行数据传输 yield将数据传 ...
- JAVA中的数据结构——集合类(序):枚举器、拷贝、集合类的排序
枚举器与数据操作 1)枚举器为我们提供了访问集合的方法,而且解决了访问对象的“数据类型不确定”的难题.这是面向对象“多态”思想的应用.其实是通过抽象不同集合对象的共同代码,将相同的功能代码封装到了枚举 ...
- ruby迭代器iterator和枚举器Enumerator
编写自定义的迭代器 The defining feature of an iterator method is that it invokes a block of code associatedwi ...
- C#中的枚举器(转)
术语表 Iterator:枚举器(迭代器) 如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.这在C# 2.0中比 C# 1.1更容 ...
- C#枚举器接口IEnumerator的实现
原文(http://blog.csdn.net/phpxin123/article/details/7897226) 在C#中,如果一个类要使用foreach结构来实现迭代,就必须实现IEnumera ...
- c# foreach枚举器
要是自己的类支持foreach ,必须在类中必须有GetEnumerator方法,该方法返回的是一个IEnumerator类型的枚举器; public class MyStruct { public ...
- C#中的foreach语句与枚举器接口(IEnumerator)及其泛型 相关问题
这个问题从<C#高级编程>数组一节中的foreach语句(6.7.2)发现的. 因为示例代码与之前的章节连贯,所以我修改了一下,把自定义类型改为了int int[] bs = { 2, 3 ...
- C#2.0中使用yield关键字简化枚举器的实现
我们知道要使用foreach语句从客户端代码中调用迭代器,必需实现IEnumerable接口来公开枚举器,IEnumerable是用来公开枚举器的,它并不实现枚举器,要实现枚举器必需实现IEnumer ...
随机推荐
- UI线程异常处理方法
当应用程序启动,创建了一个叫“main”的线程,用于管理UI相关,又叫UI线程.其他线程叫工作线程(Work Thread). Single Thread Model 一个组件的创建并不会新建一个线程 ...
- PHP微信公众平台oauth2.0网页授权登录类的封装demo
一.微信授权使用的是OAuth2.0授权的方式.主要有以下简略步骤: 第一步:用户同意授权,获取code 第二步:通过code换取网页授权access_token 第三步:拉取用户信息(需scope为 ...
- JVM学习九:JVM之GC算法和种类
我们前面说到了JVM的常用的配置参数,其中就涉及了GC相关的知识,趁热打铁,我们今天就学习下GC的算法有哪些,种类又有哪些,让我们进一步的认识GC这个神奇的东西,帮助我们解决了C 一直挺头疼的内存回收 ...
- 关于Redis数据库 ---- 基础篇
Redis数据库也被称为数据结构数据库,因为存储基于key-value模式. 其中,value值可以为字符串(string),哈希(map),列表(list),集合(set)和有序集合(zset). ...
- Alpha第一天
Alpha第一天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...
- Bate敏捷冲刺每日报告--day4
1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285) Git链接:https://github.com/WHUSE2017/C-team 2 ...
- itchat 微信的使用
#coding=utf8 import itchat # 自动回复 # 封装好的装饰器,当接收到的消息是Text,即文字消息 @itchat.msg_register('Text') def text ...
- Android类加载机制及热修复实现
Android类加载机制 Dalvik虚拟机如同其他Java虚拟机一样,在运行程序时首先需要将对应的类加载到内存中.而在Java标准的虚拟机中,类加载可以从class文件中读取,也可以是其他形式的二进 ...
- asp.net web api 控制器
1控制器操作的参数 控制器操作的参数可以是内置类型也可以是自定义类型,无参也是允许的. 2控制器操作返回值 类型 说明 void 操作返回值为void时,Web API返回空HTTP响应,其状态码为2 ...
- 04_Linux目录文件操作命令1(mv ls cd...)_我的Linux之路
上一节已经给大家讲了Linux的目录结构,相信大家已经对Linux的整个目录结构有所了解 现实中,服务器(包含Linux,Unix,windows server)一般都摆放在机房里,因为一个机房摆放了 ...