我基本上是在尝试让我的类能够使用 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
,并返回它。
这通常是通过使用嵌套(私有(private))类并返回它的一个实例来完成的。您可以将 A 类实例传递给私有(private)类(使其可以访问 data
),然后将 position
该类中的字段。它将允许同时创建多个枚举器,并将与后续的 foreach 调用一起正常工作。
例如,要修改您的代码,您需要执行以下操作:
using System;
using System.Collections;
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 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, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
return data.GetEnumerator();
}
}
最后,你可以使用iterators以更简单的方式实现这一点:
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
for (int i=0;i<data.Length;++i)
yield return data[i];
}
}
话虽如此,我强烈建议实现 IEnumerable<int>
除了IEnumerable。泛型使这在使用方面变得更好。
关于C# IEnumerable、IEnumerator 重置函数未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11475328/