【问题标题】:return type of public IEnumerator GetEnumerator()?公共 IEnumerator GetEnumerator() 的返回类型?
【发布时间】:2015-06-20 13:10:39
【问题描述】:

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

【问题讨论】:

标签: c# ienumerator


【解决方案1】:

这个函数如何返回整数

它不是,它yield returns 是一个整数。这意味着它可以编译成返回 IEnumerableIEnumerable&lt;int&gt;IEnumeratorIEnumerator&lt;int&gt; 的方法,具体取决于您的方法所说的返回。

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&lt;object&gt;IEnumerator,但这意味着编译器可以只为IEnumerable&lt;T&gt; 提供逻辑,并为非泛型类型的T 使用object,而不是使用单独的逻辑。 _state 比必要的复杂,但如果 yield-using 方法比单个循环更复杂,那么 _state 的不同值将允许它跟踪 yield-using 方法的哪个部分是对应的。

总之,它在实现IEnumerator 方面做得很好。它比您手动编写代码要大一些(并且显然比您刚刚使用 return array.GetEnumerator(); 时要大),但不会大很多,但相反,yield-using 方法要短得多,而且经常这些方法更简单。在例如以下情况下更是如此。你在yield-using 方法中有一个using 块,它会在枚举器的Dispose() 中变成适当的清理。

【讨论】:

    【解决方案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();
        }
    }
    

    【讨论】:

      【解决方案3】:

      请注意,在这种特定情况下,您可以使用数组实现“作弊”而不是真正实现 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();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-09
        • 2014-01-03
        • 2016-08-15
        • 2016-01-09
        • 2023-03-16
        相关资源
        最近更新 更多