在C#中实现自己的集合,但需要修改IEnumerable吗?

时间:2019-03-14 01:02:03

标签: c# interface ienumerable

我发现一篇很棒的文章说明了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()需要实现。那么我们该怎么做,有人可以修改代码以使其正常工作吗?

1 个答案:

答案 0 :(得分:2)

您所引用的文章代码有问题。

_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);
}