在自己的对象里实现IEnumerator和IEnumerable
2016-03-17 15:13
507 查看
平时工作中我们经常用foreach来迭代一个集合。比如
基本所有的集合都能够foreach,但是必须要实现IEnumerable接口。IEnumerable接口很简单,就只有一个IEnumerator GetEnumerator() 方法。看这个方法的定义就知道,仅仅是公开了另一个接口IEnumerator。而IEnumerator才是真正的支持一个集合的迭代。IEnumerator有1个属性和2个方法。
public object Current;
public void Reset();
public bool MoveNext();
只允许读取集合的数据,而不允许修改。为了详细的讲解,我们来写一个简单的例子,就会一目了然。
首先我们创建一个学生类Student如下:
接下来我们定义一个ClassList类来承载学生。让我们先忘记Ienmerable。这个类包含一个ArrayList字段_student,在构造函数中模拟3个学生。_student是私有的,不对外公开的。
为了让对象支持foreach 迭代,ClassList类需要实现IEnumerable。因为我们的student是存在ArrayList对象里的,而ArrayList类已经实现了IEnumerable,我们就可以使用ArrayList类的Ienumerable。
最终的代码贴一下:
然后我们调用看看使用ArrayList的Ienumerable效果:
看来还是实现了效果。那么接下来我们看看自定义实现IEnumerable。实现IEnumerable其实只要实现IEnumerator接口就可以了。
我们创建我们自己的一个自定义类ClassEnumerator 来实现IEnumerator来完成和上面相同的结果。这个类基本上就只是通过_students的索引来进行迭代,Reset()方法就是把索引设置为-1.Current属性来获取当前的student,MoveNext()来跳到Current的下一个数据,并返回一个boolean来表示是否到了集合最后。
最后修改我们的ClassLst类:
可已看到还是相当简单的。运行结果和上面是一样的。
下来看看 foreach怎么工作。
其实foreach只是语法糖,最终会被CLR翻译成
我们可以把foreach 换成这样试一下,结果是一样滴。
foreach (Student student in myClass) { Console.WriteLine(student); }
基本所有的集合都能够foreach,但是必须要实现IEnumerable接口。IEnumerable接口很简单,就只有一个IEnumerator GetEnumerator() 方法。看这个方法的定义就知道,仅仅是公开了另一个接口IEnumerator。而IEnumerator才是真正的支持一个集合的迭代。IEnumerator有1个属性和2个方法。
public object Current;
public void Reset();
public bool MoveNext();
只允许读取集合的数据,而不允许修改。为了详细的讲解,我们来写一个简单的例子,就会一目了然。
首先我们创建一个学生类Student如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { public class Student { #region 私有变量 private readonly string _id; private string _firstname; private string _lastname; #endregion #region 属性 public string ID { get { return _id; } } public string FirstName { get { return _firstname; } set { _firstname = value; } } public string LastName { get { return _lastname; } set { _lastname = value; } } #endregion #region 构造函数 public Student(string id, string firstname, string lastname) { this._id = id; this._firstname = firstname; this._lastname = lastname; } #endregion #region 重写基类object方法 public override string ToString() { return string.Format("{0} {1},ID:{2}", _firstname, _lastname, _id); } public override bool Equals(object obj) { if (obj == null) return false; if (Object.ReferenceEquals(this, obj)) return true; if (this.GetType() != obj.GetType()) return false; Student objstudent = (Student)obj; if (_id.Equals(objstudent._id)) return true; return false; } public override int GetHashCode() { return _id.GetHashCode(); } #endregion } }
接下来我们定义一个ClassList类来承载学生。让我们先忘记Ienmerable。这个类包含一个ArrayList字段_student,在构造函数中模拟3个学生。_student是私有的,不对外公开的。
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { public class ClassList { #region private Members private readonly string _id; private ArrayList _students; #endregion #region Properties public string ID { get { return _id; } } #endregion #region Constructors public ClassList(string id) { this._id = id; _students = new ArrayList() { new Student("12345", "John", "Smith"), new Student("09876", "Jane", "Doe"), new Student("76403", "Bob", "Johnson") }; } #endregion } }
为了让对象支持foreach 迭代,ClassList类需要实现IEnumerable。因为我们的student是存在ArrayList对象里的,而ArrayList类已经实现了IEnumerable,我们就可以使用ArrayList类的Ienumerable。
public IEnumerator GetEnumerator() { return (_students as IEnumerable).GetEnumerator(); }
最终的代码贴一下:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { public class ClassList:IEnumerable { #region private Members private readonly string _id; private ArrayList _students; #endregion #region Properties public string ID { get { return _id; } } #endregion #region Constructors public ClassList(string id) { this._id = id; _students = new ArrayList() { new Student("12345", "John", "Smith"), new Student("09876", "Jane", "Doe"), new Student("76403", "Bob", "Johnson") }; } #endregion public IEnumerator GetEnumerator() { return (_students as IEnumerable).GetEnumerator(); } } }
然后我们调用看看使用ArrayList的Ienumerable效果:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { class Program { static void Main(string[] args) { ClassList myClass = new ClassList("History 204"); foreach (Student student in myClass) Console.WriteLine(student); Console.ReadLine(); } } }
看来还是实现了效果。那么接下来我们看看自定义实现IEnumerable。实现IEnumerable其实只要实现IEnumerator接口就可以了。
我们创建我们自己的一个自定义类ClassEnumerator 来实现IEnumerator来完成和上面相同的结果。这个类基本上就只是通过_students的索引来进行迭代,Reset()方法就是把索引设置为-1.Current属性来获取当前的student,MoveNext()来跳到Current的下一个数据,并返回一个boolean来表示是否到了集合最后。
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { public class ClassEnumerator : IEnumerator { private ClassList _classList; private int _index; public ClassEnumerator(ClassList classList) { this._classList = classList; _index = -1; } #region IEnumerator Members public void Reset() { this._index = -1; } public object Current { get { return _classList.Students[_index]; } } public bool MoveNext() { _index++; if (_index >= _classList.Students.Count) return false; else return true; } #endregion } }
最后修改我们的ClassLst类:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { public class ClassList : IEnumerable { #region private Members private readonly string _id; private ArrayList _students; #endregion #region Properties public string ID { get { return _id; } } public ArrayList Students { get { return _students; } } #endregion #region Constructors public ClassList(string id) { this._id = id; _students = new ArrayList() { new Student("12345", "John", "Smith"), new Student("09876", "Jane", "Doe"), new Student("76403", "Bob", "Johnson") }; } #endregion public IEnumerator GetEnumerator() { return (IEnumerator)new ClassEnumerator(this); } } }
可已看到还是相当简单的。运行结果和上面是一样的。
下来看看 foreach怎么工作。
其实foreach只是语法糖,最终会被CLR翻译成
IEnumerator enumerator = myClass.GetEnumerator(); while (enumerator.MoveNext()) { Console.WriteLine((Student)enumerator.Current); }
我们可以把foreach 换成这样试一下,结果是一样滴。
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace IenumerableDemo { class Program { static void Main(string[] args) { ClassList myClass = new ClassList("History 204"); //foreach (Student student in myClass) // Console.WriteLine(student); IEnumerator enumerator = myClass.GetEnumerator(); while (enumerator.MoveNext()) { Console.WriteLine((Student)enumerator.Current); } Console.ReadLine(); } } }
相关文章推荐
- Spark的搭建
- elasticsearch.yml基本配置说明
- ubuntu技巧--ubuntu pycharm
- cooklie的另一种设置方式
- android之handler messagequene looper threadlocal 之间的详细解读
- R简单实用总结
- 哈希冲突之散列法
- hadoopSSH无密码登录
- MySQL 中的 ERROR 1366 (Mac)
- uipickerview用法
- ansible相关
- Have Lunch Together
- tableView下拉放大头部视图
- percona-toolkit使用方法
- PHP的Yii框架中YiiBase入口类的扩展写法示例
- Giraph调试尝试
- 如何在hive的shell中使用hadoop shell 和linux的命令
- 当你在浏览器地址栏输入一个URL后回车,将会发生的事情? (转)
- Autodesk技术动态简报-2016-3-17
- Linux笔记(53)——for循环