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

问题描述 投票:2回答:1

我发现了一篇很棒的文章来说明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()。那么我们怎样才能做到这一点,任何人都可以修改代码使其工作吗?

c# interface ienumerable
1个回答
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);
} 
© www.soinside.com 2019 - 2024. All rights reserved.