写博客是检验我学习的成果之一以及自我总结的一种方式,以后会经常利用这种方式进行技术交流和自我总结,其中认识不深难免会有错误,但是一直懂得不懂就问,不懂就学的道理!

  1、首先看一个简单的列子                     

      int[] myArray = { , , ,  };
    //很少这样写的
  IEnumerator myie = myArray.GetEnumerator(); //获取需要遍历的枚举数
  myie.Reset(); //重置
while (myie.MoveNext())
{
int i = (int)myie.Current; //这边涉及一个装箱的操作
Console.WriteLine("Value: {0}", i);
}
     //一般情况下是这样写的
     foreach(int item in myArray )
     {
       Console.WriteLine(item.ToString());
     }

    在大部分的情况下,很多人会使用for和foreach来遍历数组,而对于上面的语法却用的很少,但是对foreach的具体来历还很模糊!

  2、先从foreach说起                         

    大家都知道要实现foreach的必须要实现IEnumerable和IEnumerator的接口,只有实现了它们,才能实现遍历,所以要讲foreach的来历,必须要把那两个接口给搞清楚点!

     这边也想说明一点的是:如果对这两个接口有了一定的了解后,只要实现那个GetEnumerator方法即可,而不需要实现于IEnumerable接口,这只是针对对这两个接口有一定了解的朋友!

  3、IEnumerable                          

    具体的作用:就是使实现这个接口的对象成为可枚举类型。

    IEnumerable接口包含一个GetEnumerator方法,返回值为IEnumerator的类型!

    代码如下:   

    public class MyColors : IEnumerable
{
string[] colors = { "Red", "Yellow", "Biue" }; public IEnumerator GetEnumerator()
{ return colors.GetEnumerator(); }
}

那么我们在客户端进行调用的时候就可以这样做了!

     MyColors colors = new MyColors();
foreach (string item in colors)
{
Console.WriteLine(item);
}

    这样就能使用实现这个接口的对象进行foreach遍历了,就是这么简单的一个列子,这边可能有的人会有疑问,我们就实现了IEnumerable接口但却没实现IEnumerator接口,可是我们不是说只有实现了这两个接口才可以进行foreach遍历吗?可以这样说当使用forach进行遍历的时候,编译器会到这个对象的类中去寻找GetEnumerator方法,找到这个方法后返回这个一个IEnumerator的对象(枚举数),而我这边返回的是“colors.GetEnumerator()”,是一个数组对象调用它本身中的“GetEnumerator”方法,所以说数组本身就实现了IEnumerator接口,那么两个接口都实现了,不就好实现foreach遍历了,其实在实现遍历枚举数的时候编译器会自动去调用数组中实现枚举数的类中的方法(这将在下一篇中讲到)!

  4、IEnumerator                           

    接口的作用:实现可枚举数

    首先看一下接口的定义:    

    

    包含一个属性两个方法

    MoveNext → 把当前的项移动到下一项(类似于索引值),返回一个bool值,这个bool值用来检查当前项是否超出了枚举数的范围!

    Current → 获取当前项的值,返回一个object的类型(这边会涉及到装箱和拆箱的问题 → 后面讲泛型的时候会涉及到)!

    Reset → 顾名思义也就是把一些值恢复为默认值,比如把当前项恢复到默认状态值!

    代码如下:  

     public class MyIEnumerator : IEnumerator
{ string[] colors;    //定义一个数组,用来存储数据
int position = -;   //定义当前项的默认值,也就是索引值,一开始认识数组的索引从“0”开始,怎么默认设置他为“-1”呢,最后才想明白,这样设置是合情合理的! public MyIEnumerator(string[] colors)
{
this.colors = new string[colors.Length]; for (int i = ; i < this.colors.Length; i++)
{
this.colors[i] = colors[i];
}
} public object Current //根据当前项获取相应的值
{
get
{
return colors[position];  //返回当前项的值,但是会做一个装箱的操作!
}
} public bool MoveNext()     //移动到下一项
{
if (position < colors.Length - )   //这就是设置默认值为-1的根据
{
position++;
return true;
}
else
{
return false;
}
} public void Reset()   //重置当前项的值,恢复为默认值
{
this.position = -;
}
}

在第三点讲到的IEnumerable接口中GetEnumerator方法是获取要遍历的枚举数,在我们没有创建自己的遍历枚举数的类时,我们使用的是Array的遍历枚举数的方法(关于数组的可枚举类型和枚举数会在下一篇讲到),但这个有的时候不一定适合我们,我们需要为自己定制一个更合适的,所以我们要创建自己的枚举数类(也就是上面的代码),把第三点和第四点的代码合并起来(改动一点代码),如下: 

    public class MyColors   //: IEnumerable
{
string[] colors = { "Red", "Yellow", "Biue" }; public IEnumerator GetEnumerator()
{
return new MyIEnumerator(colors); //这边就是我们要改动的地方,返回一个自己创建的类型,不是在返回数组的IEnumerator对象了,而是我们自己创建的枚举数对象→MyIEnumerator
}
}

  客户端是不要改动代码的,然后只要使用foreach直接遍历就可以了!

    

  5、关于可枚举类型和枚举数                      

    ①可枚举类型 → 实现IEnumerable接口,可以不需要直接实现这个接口,但必须有个GetEnumerator方法,返回值类型必须为IEnumerator类型,也就是第四点最后一段代码中接口注释的那种写法!

    ②枚举数 → 实现IEnumerator接口,实现全部方法,首先是调用GetEnumerator返回一个类型为IEnumerator的枚举数,然后编译器会隐式的调用实现IEnumerator类中的方法和属性!

    总结:所以实现foreach遍历,必须达到上面的两种条件才能进行遍历对象,他们可以写在一起也可以分开,最好是分开,进行职责分离,一个类干一件事总归是好事!

  6、图示,引用书中的图片                       

    

  希望园子里面的朋友能过多多指教! 

迭代器学习之一:使用IEnumerable和IEnumerator接口的更多相关文章

  1. IEnumerable、IEnumerator接口(如何增加迭代器功能)

    IEnumerable.IEnumerator接口封装了迭代器功能,有了它,我们不需要将内部集合暴露出去,外界只需要访问我的迭代器接口方法即可遍历数据. 在C#中,使用foreach语句来遍历集合.f ...

  2. 细说 C# 中的 IEnumerable和IEnumerator接口

    我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...

  3. C# IEnumerable 和 IEnumerator接口浅析

    温故而知新,可以为师矣,有空经常复习一下基础知识是有必要的,并且能加深理解和记忆. Foreach常用于循环访问集合,对实现IEnumerable的接口的容器进行遍历,IEnumerable和IEnu ...

  4. IEnumerable和IEnumerator接口

    我们先思考几个问题:1.为什么在foreach中不能修改item的值?(IEnumerator的Current为只读)2.要实现foreach需要满足什么条件?(实现IEnumerator接口来实现的 ...

  5. C#基础知识系列九(对IEnumerable和IEnumerator接口的糊涂认识)

    前言 IEnumerable.IEnumerator到现在为止对这两个接口还是不太理解,不理解但是自己总是想着试着要搞明白,毕竟自己用的少,所以在此先记录一下.以备自己日后可以来翻查,同时也希望园子里 ...

  6. 【转】【C#】迭代器IEnumerable和IEnumerator

    迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式.简单来说,迭代器模式使得你能够获取到序列中的所有元素而 ...

  7. C# ~ 从 IEnumerable / IEnumerator 到 IEnumerable<T> / IEnumerator<T> 到 yield

    IEnumerable / IEnumerator 首先,IEnumerable / IEnumerator 接口定义如下: public interface IEnumerable /// 可枚举接 ...

  8. IEnumerable和IEnumerator

    概述 IEnumerable和IEnumerator接口存在的意义:用来实现迭代的功能! public interface IEnumerable { IEnumerator GetEnumerato ...

  9. 在C#中IEnumerable与IEnumerator

    对于很多刚开始学习C#同学来说经常会遇到IEnumerable这个关键字,enumerate在字典里的解释是列举,枚举,因此可想而知这个关键字肯定是和列举数据有关的操作. public interfa ...

随机推荐

  1. YARN与MRv1的对比

    YARN与MRv1的对比 转载请注明出处:http://www.cnblogs.com/BYRans/ Hadoop 1.0存在的问题 由于Hadoop 1.0的良好特性,Hadoop 1.0被应用到 ...

  2. [django]利用xlwt实现文件下载功能

    代码: url.py: url(r'^importmould/$', 'keywork.views.xls_mould', name='xls_mould'), view.py: from djang ...

  3. NOIP复习赛20161117

    题目链接:http://files.cnblogs.com/files/candy99/%E9%A2%98%E7%9B%AE1117.pdf A n个等比数列求和公式(都感觉数列忘光了) %1e9+7 ...

  4. 解决win10卡顿现象

    前两天打开了windows defender,想着既然是window自带的防护工具,应该效果不错.经过测试之后 ,发现这个要占用很大内存,得不偿失.如果想要保证系统安全,甚至腾讯电脑管家做的都比这个w ...

  5. Java中单例

    Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例.饿汉式单例 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3. ...

  6. SpringFrameWork 上下文工具类

    //Servlet上下文ServletContext application = event.getServletContext(); //Spring应用上下文ApplicationContext ...

  7. Map接口使用注意事项

    1,Map接口对象本身不能直接使用迭代进行输出的.因为map每个位置存放的是一对值. 而iterator每次只能找到一个值.如果一定要迭代输出,可以通过以下步骤.: 但是,Map接口只作为查找使用,输 ...

  8. .Net的内置对象之一 Request

    一.Request简介 Request对象是.net的内置对象之一,也是.net中常用的对象,用于获取客户端的信息,可以使用Request对象访问任何基于HTTP请求传递的所有信息.通过Request ...

  9. rsyslog及logrotate小结

    [root@node1 logrotate.d]# ls dracut haproxy httpd mcelog nginx ppp psacct syslog yum   yum install n ...

  10. ConcurrentHashMap和HashMap的一点区别

    HashMap不是线程安全的,ConcurrentHashMap则在某一个方法的执行上是线程安全的. package testMap; import java.util.HashMap; public ...