返回类型的公共IEnumerator GetEnumerator()?

时间:2015-06-20 13:10:39

标签: c# ienumerator

要实现集合,我必须完成GeEnumerator()。但是这个函数的返回类型是IEnumerator。怎么做到呢 ? 例如..

class MyList : IEnumerable, IEnumerator
{
    private int[] array;
    int positino = -1;        
    public IEnumerator GetEnumerator()
    {
        for(int i = 0 ; i < array.Length; ++i)
        {
              yield return array[i];
        }
    }
}

array [i]是整数而不是IEnumerator类型。该函数如何返回整数?

3 个答案:

答案 0 :(得分:2)

使用泛型和IEnumerable int

public class MyList : IEnumerable<int>
{
    public MyList()
    {
        array = new [] { 1, 2, 3, 4, 5, 6, 7};
    }

    private int[] array;
    int positino = -1;        
    public IEnumerator<int> GetEnumerator()
    {
        for(int i = 0 ; i < array.Length; ++i)
        {
              yield return array[i];
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

答案 1 :(得分:2)

  

该函数如何返回整数

它没有,它yield return是一个整数。这意味着它可以编译成一个返回IEnumerableIEnumerable<int>IEnumeratorIEnumerator<int>的方法,具体取决于您返回的方法。

yield关键字是一种便利,可以创建具有相应MoveNext()CurrentDispose的枚举数,如果它是可枚举的,那么适当的GetEnumerator

看看你的方法:

public IEnumerator GetEnumerator()
{
  for(int i = 0 ; i < array.Length; ++i)
  {
      yield return array[i];
  }
}

然后这是可以编译的东西,但是为了真正起作用,它需要更多来实际分配给array

当我们编译它时,它的结果与我们编写的结果相同:

private class En : IEnumerator<object>
{
  private object _current;
  private int _state;
  public MyList _this;
  public int _index;
  public bool MoveNext()
  {
    int state = _state;
    switch(state)
    {
      case 0:
        _state = -1;
        _index = 0;
        break;
      case 1:
        _state = -1;
        if(++_index >= _this.array.Length)
          return false;
        break;
      default:
        return false;
    }
    _current = _this.array[_index];
    _state = 1;
    return true;
  }
  public object Current
  {
    get { return _current; }
  }
  public void Reset()
  {
    throw new NotSupportedException();
  }
  public void Dispose()
  {
  }
  object IEnumerator.Current
  {
    get { return _current; }
  }
  public En(int state)
  {
    _state = state;
  }
}
public IEnumerator GetEnumerator()
{
  var en = new En(0);
  en._this = this;
  return en;
}

主要区别在于En及其字段的名称都不是有效的C#名称,而是有效的.NET名称,因此它不能与程序员使用的任何名称冲突。

这比它需要的更多。它实现了IEnumerator<object>以及IEnumerator,但这意味着编译器可以只有IEnumerable<T>的逻辑,并使用object作为非T泛型类型而不是具有单独的逻辑。 _state比必要的更复杂,但如果yield - 使用方法比单个循环更复杂,那么_state的不同值将允许它跟踪哪个部分yield - 使用与之对应的方法。

总之,在实施IEnumerator方面做得很好。它比你手工编写一个(比你刚刚使用return array.GetEnumerator();时要大一些)要大一些,但不是更大,但相反yield - 使用方法是一个更短,通常这些方法更简单。在例如以下情况下更是如此。您在using - 使用方法中有一个yield块,它会在枚举器的Dispose()中转换为相应的清理。

答案 2 :(得分:1)

请注意,在这种特定情况下,您可以使用数组实现“作弊”而不是真正实现public class MyList : IEnumerable<int> { public MyList() { array = new[] { 1, 2, 3, 4, 5, 6, 7 }; } private int[] array; public IEnumerator<int> GetEnumerator() { return ((IEnumerable<int>)array).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }

!important