返回公共 IEnumerator GetEnumerator() 的类型

本文关键字:类型 GetEnumerator IEnumerator 返回 | 更新日期: 2023-09-27 17:57:22

要实现集合,我必须完成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 类型。这个函数怎么能返回整数?

返回公共 IEnumerator GetEnumerator() 的类型

这个函数怎么能返回整数

没有,它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 -using 方法比单个循环更复杂,则 _state 的不同值将允许它跟踪该yield -using 方法的哪个部分与之对应。

总而言之,它在实施IEnumerator方面做得很好。它比手动编码一个要大一点(显然比你只使用return array.GetEnumerator();大),但不是大很多,但相反,yield-use 方法要短得多,通常这些方法更简单。例如,在 yield -using 方法中有一个using块的情况下更是如此,该块在枚举器的Dispose()中变成了适当的清理。

使用泛型和 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();
    }
}

请注意,在这种特定情况下,您可以使用数组实现"作弊"而不是真正实现GetEnumerator()

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