我发现了一篇很棒的文章来说明IEnumerable和IEnumerator
https://programmingwithmosh.com/csharp/ienumerable-and-ienumerator/
以下是源代码:
public class List : IEnumerable
{
private object[] _objects;
public List()
{
_objects = new object[100];
}
public void Add(object obj)
{
_objects[_objects.Count] = obj;
}
public IEnumerator GetEnumerator()
{
return new ListEnumerator(); //region 1
}
private class ListEnumerator : IEnumerator
{
private int _currentIndex = -1;
public bool MoveNext()
{
_currentIndex++;
return (_currentIndex < _objects.Count);
}
public object Current
{
...
}
public void Reset()
{
_currentIndex = -1;
}
}
}
我在本文中发现了一些错误,可能是一些错误如_objects.Count
应该是_objects.Length
,但一个基本问题是:如何在ListEnumerator中访问_objects
?所以我想我需要在区域1中传递'this'
public IEnumerator GetEnumerator()
{
return new ListEnumerator(this);
}
并将ListEnumerator修改为:
private class ListEnumerator : IEnumerator
{
private int _currentIndex = -1;
IEnumerable aggregate = null;
public ListEnumerator(IEnumerable param)
{
aggregate = param
}
public bool MoveNext()
{
_currentIndex++;
return (_currentIndex < aggregate.Count); //important region
}
public object Current
{
//don't worry about the boundary check/exceptions
get
{
return aggregate[_currentIndex]; //important region
}
}
...
}
为了做到这一点,IEnumerable也需要像
interface IEnumerable
{
IEnumerator GetEnumerator();
int Count{get;}
object this[int itemIndex]{set;get;}
}
但我们都知道IEnumerable
只有一种需要实施的方法GetEnumerator()
。那么我们怎样才能做到这一点,任何人都可以修改代码使其工作吗?
您所指的文章代码存在问题。
_objects
是班级List
的私人成员,所以它不能在课外访问,即使是来自List
的外星人。
即使你公开_objects
,也不能在没有创建List
类的对象的情况下访问它。
此外,没有办法可以修改IEnumerable
界面。
我建议采用两种方法。
方法1
更改ListEnumerator
类构造函数以接受List
类的对象
private class ListEnumerator : IEnumerator
{
private List _list;
public ListEnumerator(List list)
{
this._list = list;
}
private int _currentIndex = -1;
public bool MoveNext()
{
_currentIndex++;
return (_currentIndex < this._list._objects.Length);
}
public object Current
{
get
{
try
{
return this._list._objects[_currentIndex];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public void Reset()
{
_currentIndex = -1;
}
}
您还需要从private
类中的_objects
声明中删除List
。并将this
传递给ListEnumerator构造函数。
public class List : IEnumerable
{
object[] _objects;
public List()
{
_objects = new object[100];
}
//Other code of List class.
public IEnumerator GetEnumerator()
{
return new ListEnumerator(this);
}
}
方法2
更改ListEnumerator
类构造函数以接受对象数组。
private class ListEnumerator : IEnumerator
{
private object[] _objects;
public ListEnumerator(object[] objects)
{
this._objects = objects;
}
private int _currentIndex = -1;
public bool MoveNext()
{
_currentIndex++;
return (_currentIndex < this._objects.Length);
}
public object Current
{
get
{
try
{
return this._objects[_currentIndex];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public void Reset()
{
_currentIndex = -1;
}
}
并在List类中使用它如下。
public IEnumerator GetEnumerator()
{
return new ListEnumerator(this._objects);
}