数组可以被foreach语句遍历数组中的元素,原因是数组可以按需提供一个叫做枚举数(enumerator)的对象.枚举数可以依次返回请求的数组的元素. 
对于有枚举数的类型而言,必须有一个方法来获取它们.在.NET中获取一个对象枚举数的标准用法是调用对象的GetEnumerator方法.实现GetEnumerator方法的类型叫做可枚举类型(enumerable),数组就是可枚举类型. 
要注意枚举数(enumerator)和可枚举类型(enumerable)的区别和联系. 
枚举数是可以依次返回集合项的类对象,可枚举类型是带有GetEnumerator方法的类型,它返回枚举数. 
当foreach被用来遍历可枚举类型时,它就会执行如下的行为: 
1,通过调用GetEnumerator方法获取对象的枚举数. 
2,从枚举数中请求每一项并且把它作为迭代变量,代码可以读但不可以改变.

枚举数共有3种,可以用以下方式来实现枚举数: 
1 IEnumerator/IEnumerable接口   ,叫做非泛型接口形式. 
2 IEnumerator<T>/IEnumerable<T>接口,   叫做泛型接口形式. 
3 不使用接口形式. 
IEnumerator接口 
IEnumerator接口包含3个函数成员:Current,MoveNext,Reset 
Current返回序列中当前项的属性,它是一个只读属性.返回object类型的引用,所以可以返回任何类型. 
MoveNext是把枚举数位置前进到集合的下一项的方法,它返回布尔值,指示新位置是有效位置还是已经超过了序列的尾部.如果是已经到达了尾部,则返回false. 
Reset方法把位置重置为原始状态. 
查看下面的代码:

int[] MyArray = { 10, 11, 12, 13 };                           //创建数组 
IEnumerator ie = MyArray.GetEnumerator();         //获取枚举数 
while (ie.MoveNext())                                             //移到下一项 
    Console.WriteLine((int)ie.Current);                   //获取当前项并输入 
枚举数的初始位置是-1,所以要想获取第一个元素就必须执行MoveNext()方法. 
上面的代码就是调用枚举数的Current和MoveNext成员函数手工地遍历数组中的元素. 
或者可以直接使用foreach直接获取: 
foreach(int i in MyArray) 
     Console.WriteLine(i); 
下面列出一个颜色名数组的枚举数类: 
using System.Collections;

class ColorEnumerator : IEnumerator 
    { 
        private string[] Colors; 
        private int Position = -1; 
        public object Current 
        { 
            get 
            { 
                if (Position == -1) 
                    throw new InvalidOperationException(); 
                if (Position == Colors.Length) 
                    throw new InvalidOperationException(); ; 
                return Colors[Position]; 
   } 
        } 
        public bool MoveNext() 
        { 
            if (Position < Colors.Length - 1) 
            { 
                Position ++; 
                return true; 
            } 
            else 
                return false; 
        }

public void Reset() 
        { 
Position = -1; 
        } 
        public ColorEnumerator(string[] theColors)              //构造函数 
        { 
            Colors = new string[theColors.Length]; 
            for (int i = 0; i < theColors.Length - 1; i++) 
                Colors[i] = theColors[i]; 
        } 
    }

以上代码就构造了一个完整的枚举数类型.下面生成对象返回枚举数. 
    class Program 
    { 
        static void Main() 
        { 
            ColorEnumerator ce = new ColorEnumerator(new string[]{"yellow","red","white","black"}); 
            while (ce.MoveNext()) 
                Console.WriteLine((string)(ce.Current)); 
  Console.ReadKey(); 
        } 
    } 
如果要用foreach来遍历枚举数,需要再定义一个可枚举类型的类,这个类要实现IEnumerable接口的功能. 
public interface IEnumerable 

    IEnumerator GetEnumerator(); 
}

class MyEnumerable : IEnumerable           //定义一个可枚举类型的类 
    { 
        string[] MyColor = new string[] { "yellow", "red", "black", "white" }; 
        public IEnumerator GetEnumerator()    //实现接口        
        { 
            return new ColorEnumerator(MyColor);      //返回一个枚举数的对象 

    } 
现在就可以使用foreach来遍历可枚举类型对象的所有元素了. 
   class Program 
    { 
        static void Main() 
        { 
            MyEnumerable me = new MyEnumerable(); 
            foreach (string i in me) 
                Console.WriteLine(i); 
            Console.ReadKey(); 
        } 
    }

总结一下,如果想遍历一个对象中的所有元素,可以把对象设为枚举数类型(实现IEnumerator接口)和可枚举的类类型(实现IEnumerable接口),前者需要实现IEnumerator接口的Current,MoveNext和Rest成员函数,后者需要实现IEnumerable接口的GetEnumerator成员函数,由于GetEnumerator返回的是IEnumerator对象,所以还要建立一个派生于IEnumerator的枚举数类,在这个类中实现Current,MoveNext和Reset成员函数.派生于IEnumerable的类可以使用foreach代码来遍历对象中的全部元素.

摘自:syexy的博客

C#的枚举数(Enumerator)和可枚举类型(Enumerable)的更多相关文章

  1. C#枚举数和迭代器

    大道至简,始终认为简洁是一门优秀的编程语言的一个必要条件.相对来说,C#是比较简洁的,也越来越简洁.在C#中,一个关键字或者语法糖在编译器层面为我们做了很多乏味的工作,可能实现的是一个设计模式,甚至是 ...

  2. 【C#】IEnumrator的枚举数和IEnumerable接口

    声明IEnumerator的枚举数 要创建非泛型接口的枚举数,必须声明实现IEnumerator接口的类,IEnumerator接口有如下特性: 1.她是System.Collections命名空间的 ...

  3. 实现自定义集合的可枚举类型(IEnumerable)和枚举数(IEnumerator )

    下面的代码示例演示如何实现自定义集合的 IEnumerable 和 IEnumerator 接口: using System; using System.Collections; using Syst ...

  4. java枚举与.net中的枚举区别

    通过一段时间的项目实践,发现java中的枚举与.net中的枚举有很大的差别,初期造成了我对java中的枚举一些错误理解及部分有缺陷的应用,其实追其原因还是因为我会习惯性的认为java的枚举在作用以及定 ...

  5. C# 给枚举定义DescriptionAttribute,把枚举转换为键值对

    在C#中,枚举用来定状态值很方便,例如我定义一个叫做Season的枚举 public enum Season { Spring = 1, Summer = 2, Autumn = 3, Winter ...

  6. 【C/C++开发】C++之enum枚举量声明、定义、使用与枚举类详解与枚举类前置类型声明

    众所周知,C/C++语言可以使用#define和const创建符号常量,而使用enum工具不仅能够创建符号常量,还能定义新的数据类型,但是必须按照一定的规则进行,下面我们一起看下enum的使用方法. ...

  7. Swift 枚举-从汇编角度看枚举内存结构

    一.基本使用 先看枚举的几种使用(暂不要问,看看是否都能看懂,待会会逐一讲解) 1.操作一 简单使用 //第一种方式 enum Direction { case east case west case ...

  8. 暴力枚举-数长方形(hdu5258)

    数长方形 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

    1 数组排序 1.1 问题 本案例实现一个整型数组排序的函数,数组排序的规则由传递的规则函数决定. 1.2 方案 首先定义一个整型数组排序函数sortInts,该函数有一个整型数组类型的参数,该参数必 ...

随机推荐

  1. 聚焦 SQL 数据库活动异地复制

    Tobias Ternstrom  US-DS-PM 首席部门项目经理 本文作为一系列业务连续性和灾难恢复文章的开篇,概述了业务连续性的各种场景,然后重点介绍 SQL 数据库高级服务级别提供的活动异地 ...

  2. UVa 11300 Spreading the Wealth 分金币

    圆桌旁坐着 n 个人,每个人都有一定数量的金币,金币总数能够被 n 整除.每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等.你的任务是求出被转手的金币数量的最小值,比如 n = 4, ...

  3. Android 如何直播RTMP流

    在android上,视频/音频流直播是极少有人关注的一部分.每当我们讨论流媒体,RTMP(Real Time Messaging Protocol)是不可或缺的.RTMP是一个基本的视频/音频直播流协 ...

  4. Delphi ORD

    //Char 类型与其编码值的转换:varb: Byte;c: Char;beginb := Ord('A');   {返回: 65}b := Ord(#65);   {返回: 65}b := Ord ...

  5. solr4.2 solrconfig.xml配置文件简单介绍

    对于solr4.x的每个core有两个很重要的配置文件:solrconfig.xml和schema.xml,下面我们来了解solrconfig.xml配置文件. 具体很详细的内容请细读solrcofi ...

  6. 底部菜单栏(一) TabHost实现

    需求:使用TabHost实现底部菜单栏: 效果图: 实现分析: 1.目录结构: 代码实现: 1.activity_main.xml <?xml version="1.0" e ...

  7. Zend Framework 入门(1)—快速上手

    1. 安装 从 Zend Framework 的网页上下载最新版本.解压后,把整个目录拷贝到一个理想的地方,比如:/php/library/Zend. 打开 php.ini 文件,确认包含 Zend ...

  8. C#网络资源列表

    1, http://club.topsage.com/thread-371996-1-1.html

  9. Matlab编程实例(4) 相位角与相关系数曲线

    %相位角与相关系数曲线 close all; clear all; Samp1=200;  %设置信号的采样精度 Samp2=200;  %设置相位角p分割精度 A=10;%信号幅值 w=1;%信号角 ...

  10. Python面向对象2

    方法 公共方法 私有方法 类方法 静态方法 #!usr/bin/python #coding:utf8 class Milo(): name = 'csvt' def fun1(self): prin ...