zoukankan      html  css  js  c++  java
  • 【转】C#学习之用迭代器实现枚举器

    http://www.cnblogs.com/zouzf/archive/2012/02/22/2362954.html

    本人初学C#,本文仅供个人整理思路用,那里说得不对,请大家多多指教,万分感激!

    上一篇文章为自定义类实现了foreach的功能,但实现过程中要实现IEnumerator接口(包括MoveNext、Reset函数和Current属性)以便GetEnumerator函数能获取枚举数,有点复杂,有点繁琐。

    已经知道:主要一个类实现了GetEnumerator函数就能foreach,而实现IEnumerator接口只是实现GetEnumerator函数的其中一个办法,也就说还有其他办法实现GetEnumerator函数了?是的,C#2.0为我们提供了一种很简单的方法来实现GetEnumerator函数,那就是使用迭代器!(还记得吧,C#里的迭代器和C++里的是不同的)

    下面是来自MSDN的解说:

    迭代器概述
    迭代器是可以返回相同类型的值的有序序列的一段代码。

    迭代器可用作方法、运算符或 get 访问器的代码体。

    迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代。有关更多信息,请参见 yield。

    可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示:foreach(int x in SampleClass.Iterator2){}

    迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。

    yield 关键字用于指定返回的值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。

    第一部分:使用默认迭代器实现获取枚举数
    1、定义Person类


    复制代码
    1 public class Person
    2 {
    3 public string Name;
    4 public int Age;
    5
    6 public Person(string name, int age)
    7 {
    8 Name = name;
    9 Age = age;
    10 }
    11
    12 public override string ToString()
    13 {
    14 return "Name: " + Name + " Age: " + Age;
    15 }
    16 }
    复制代码

    2、定义PeopleEnum1类,里面实现了GetEnumerator函数(也就是迭代器了,这是默认的迭代器),但实现的过程相对于上一篇文章里介绍的实现过程要简单很多,这就是yield的功效。yield的实现原理这里就不详说了,可以概括为:GetEnumerator函数里的迭代块把 IEnumerator接口的MoveNext、Reset方法和Current属性封装了,但本质没变,只是我们使用起来更方便了。

    复制代码
    1 public class PeopleEnum1
    2 {
    3 private Person[] _perple;
    4
    5 //构造函数
    6 public PeopleEnum1(Person[] list)
    7 {
    8 _perple = new Person[list.Length];
    9 for (int i = 0; i < list.Length; i++)
    10 {
    11 _perple[i] = list[i];
    12 }
    13 }
    14
    15 public IEnumerator GetEnumerator()
    16 {
    17 for (int i = 0; i < _perple.Length; i++)
    18 {
    19 yield return _perple[i];
    20 }
    21 }
    22
    23 }
    复制代码

    3、主函数代码


    复制代码
    1 class Program
    2 {
    3 static void Main(string[] args)
    4 {
    5 Person[] persons = new Person[]
    6 {
    7 new Person("aaa", 20),
    8 new Person("bbb", 21),
    9 new Person("ccc", 22)
    10 };
    11
    12 PeopleEnum1 peopleEnum = new PeopleEnum1(persons);
    13
    14 foreach (var item in peopleEnum)
    15 {
    16 System.Console.WriteLine(item);
    17
    18 }
    19
    20 System.Console.ReadKey();
    21 }
    22 }
    复制代码
    运行,成功,嘿嘿

    第二部分:自定义迭代器

    第一部分用默认迭代器GetEnumerator 实现了类的foreach,我们也可以定义自己的迭代器来获取自己想要的枚举数。比较说,我想列举出类中未成年人的信息,默认的迭代器无能为力,该怎么实现自定义的迭代器呢?

    1、为PeopleEnum1类添加一个迭代器 GetChildren ,在这里,这个迭代器是一个属性,也可以定义为函数。对于类中的元素,只有Age 小于18的元素才 yield return ,其他的不要。


    复制代码
    1 public class PeopleEnum1
    2 {
    3 private Person[] _perple;
    4
    5 //构造函数
    6 public PeopleEnum1(Person[] list)
    7 {
    8 _perple = new Person[list.Length];
    9 for (int i = 0; i < list.Length; i++)
    10 {
    11 _perple[i] = list[i];
    12 }
    13 }
    14
    15 //默认的迭代器?
    16 public IEnumerator GetEnumerator()
    17 {
    18 for (int i = 0; i < _perple.Length; i++)
    19 {
    20 yield return _perple[i];
    21 }
    22 }
    23
    24
    25 //自定义迭代器
    26 public IEnumerable GetChildren
    27 {
    28 get
    29 {
    30 for (int i = 0; i < _perple.Length; i++)
    31 {
    32 if (_perple[i].Age < 18)
    33 {
    34 yield return _perple[i];
    35 }
    36 }
    37 }
    38 }
    39 }
    复制代码

    2、主函数代码


    复制代码
    1 class Program
    2 {
    3 static void Main(string[] args)
    4 {
    5 Person[] persons = new Person[]
    6 {
    7 new Person("aaa", 16),
    8 new Person("bbb", 18),
    9 new Person("ccc", 22)
    10 };
    11
    12
    13 PeopleEnum1 peopleEnum = new PeopleEnum1(persons);
    14
    15 foreach (var item in peopleEnum)
    16 {
    17 System.Console.WriteLine(item);
    18 }
    19
    20
    21 Console.WriteLine(" 集合中未成年人的信息");
    22
    23 foreach (var item in peopleEnum.GetChildren)
    24 {
    25 Console.WriteLine(item);
    26 }
    27
    28 System.Console.ReadKey();
    29 }
    30 }
    复制代码

    输出结果:

    输出结果:

    可以看到,自定义的迭代器 GetChildren 成功foreach了。

    注意:默认迭代器 GetEnumerator 的返回类型是 IEnumerator ,并且在使用foreach时 in 后面直接是类名。而自定义迭代器 GetChildren 的返回类型是 IEnumerable,并且在使用foreach时 in 后面是 PeopleEnum.GetChildren(类名.迭代器名)。好像,好像是规定这样子的,原理是什么还不清楚。

  • 相关阅读:
    Unity 粒子系统 特效 移除屏幕外面后再移回来 不会显示问题
    同步读取各平台StreamingAssets文件
    cocos2d-x for android 环境搭建&交叉编译
    lua 热更新
    php连接mysql超时问题
    svn仓库自动同步(主库、从库自动同步)
    游戏开发进度、状况以及结果的关系(个人感言)
    centos 重启服务命令
    编译时,输出信息重定向到文件
    vs开发的程序内存错误
  • 原文地址:https://www.cnblogs.com/mimime/p/5698197.html
Copyright © 2011-2022 走看看