我基本上试图让我的类能够使用foreach进行迭代.我读了这个教程.
MSDN.看起来非常直截了当.但是,当我想第二次迭代时,我遇到了问题.我调试了它;事实证明它没有调用Reset()函数.
A级
class A : IEnumerable,IEnumerator { int[] data = { 0,1,2,3,4 }; int position = -1; public object Current { get { return data[position]; } } public bool MoveNext() { position++; return (position < data.Length); } public void Reset() { position = -1; } public IEnumerator GetEnumerator() { return (IEnumerator)this; } }
当我运行以下主要功能时;它永远不会调用Reset()函数.所以,经过一个循环,我再也无法迭代我的课了.
主要
static void Main(string[] args) { A a = new A(); foreach (var item in a) { Console.WriteLine(item); } Console.WriteLine("--- First foreach finished. ---"); foreach (var item in a) { Console.WriteLine(item); } }
输出:
0 1 2 3 4 --- First foreach finished. --- Press any key to continue . . .
有什么想法吗?
解决方法
每次调用foreach时,都会要求新的IEnumerator.返回你的类实例是一个坏主意 – 你应该创建一个单独的类来实现IEnumerator,然后返回它.
这通常通过使用嵌套(私有)类并返回它的实例来完成.您可以将类A实例传递给私有类(使其可以访问数据),并将位置字段放在该类中.它将允许同时创建多个枚举器,并且可以与后续的foreach调用一起正常工作.
using System; using System.Collections; class A : IEnumerable { int[] data = { 0,4 }; public IEnumerator GetEnumerator() { return new AEnumerator(this); } private class AEnumerator : IEnumerator { public AEnumerator(A inst) { this.instance = inst; } private A instance; private int position = -1; public object Current { get { return instance.data[position]; } } public bool MoveNext() { position++; return (position < instance.data.Length); } public void Reset() { position = -1; } } }
请注意,您也可以直接返回数组的枚举器(虽然我假设您正在尝试学习如何创建干净的枚举器):
class A : IEnumerable { int[] data = { 0,4 }; public IEnumerator GetEnumerator() { return data.GetEnumerator(); } }
最后,您可以使用iterators以更简单的方式实现此功能:
class A : IEnumerable { int[] data = { 0,4 }; public IEnumerator GetEnumerator() { for (int i=0;i<data.Length;++i) yield return data[i]; } }
话虽这么说,我强烈建议实现IEnumerable< int>除了IEnumerable.仿制药在使用方面做得更好.