>1 IEnumerator与IEnumerable
IEnumerator与IEnumerable两个接口是用于实现迭代器的接品只要实现了IEnumerable就可以用foreach,linq等语法,一般来说实现 IEnumerable接口的是Collection的数据,也就是一个集合,比如List,ArrayList等这种类型,因为一般foreach,linq都是在一个集合中查询
而IEnumerator主要是支持IEnumerator一个接口,里面提供了用于迭代的属 性和方法,两个接口代码
public interface IEnumerable{ IEnumerator GetEnumerator(); } public interface IEnumerable{ object Current{get;} bool MoveNext(); void Reset(); }
下面是简单实现自己类支持迭代
public class Man { public string Name { get; set; } public int Age { get; set; } public override string ToString() { return string.Format("{0} {1}", Name, Age); } } public class ManEnum : IEnumerator { private Man[] man; private int index = -1; public ManEnum(Man[] man) { this.man = man; } public object Current { get { return man[index]; } } public bool MoveNext() { index++; return index < man.Length; } public void Reset() { index = -1; } } public class ManCollection : IEnumerable { private ManEnum me; public ManCollection(Man[] man) { this.me = new ManEnum(man); } public IEnumerator GetEnumerator() { return me; } }
下面测试可以用foreach打印信息出来
Man[] man = { new Man() { Name = "小明", Age = 20 }, new Man() { Name = "小红", Age = 19 } }; ManCollection mc = new ManCollection(man); foreach (var m in mc) { Console.WriteLine(m); }
>2 yield我们可以用yield更方便快捷的写出迭代器,可以实现返回IEnumerable或 IEnumerator的对象
下面是用yield修改的代码,我们可以直接去掉ManEnum类.把ManCollection 改一下
public class ManCollection : IEnumerable { private Man[] mans; public ManCollection(Man[] man) { this.mans = man; } public IEnumerator GetEnumerator() { for (int i = 0; i < mans.Length; i++) { yield return mans[i]; } } }
这次我们用linq来查询出年龄大于等于18岁的.
Man[] man = { new Man() { Name = "小明", Age = 20 }, new Man() { Name = "小红", Age = 19 } }; ManCollection mc = new ManCollection(man); var q = from r in man where r.Age >= 18 select r; foreach (var x in q) { Console.WriteLine(x); }
可以看出没有问题,yield还有一种就是yield break;可以在迭代过程中打段
,类似于循环中break一样的效果.