【问题标题】:How would you implement the IEnumerator interface?您将如何实现 IEnumerator 接口?
【发布时间】:2008-09-10 13:05:56
【问题描述】:

我有一个将对象映射到对象的类,但与字典不同,它以两种方式映射它们。我现在正在尝试实现一个自定义的IEnumerator 接口,该接口遍历值。

public class Mapper<K,T> : IEnumerable<T>, IEnumerator<T>

{
    C5.TreeDictionary<K,T> KToTMap = new TreeDictionary<K,T>();
    C5.HashDictionary<T,K> TToKMap = new HashDictionary<T,K>();

    public void Add(K key, T value)
    {
        KToTMap.Add(key, value);
        TToKMap.Add(value, key);

    }

    public int Count
    {
        get { return KToTMap.Count; }
    }
    

    public K this[T obj]
    {
        get
        {
            return TToKMap[obj];
        }
    }

    public T this[K obj]
    {
        get
        {
            return KToTMap[obj];
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return KToTMap.Values.GetEnumerator();
    }

    public T Current
    {
        get { throw new NotImplementedException(); }
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    object System.Collections.IEnumerator.Current
    {
        get { throw new NotImplementedException(); }
    }

    public bool MoveNext()
    {
        ;
    }

    public void Reset()
    {
        throw new NotImplementedException();
    }
}

【问题讨论】:

    标签: c# .net collections ienumerable ienumerator


    【解决方案1】:

    首先,不要让你的集合对象实现 IEnumerator。这会导致错误。 (考虑两个线程在同一个集合上迭代的情况)。

    事实证明,正确实现枚举器并非易事,因此 C# 2.0 基于“yield return”语句添加了特殊语言支持。

    Raymond Chen 最近的一系列博客文章(“C# 中迭代​​器的实现及其后果”)是了解最新进展的好地方。

    【讨论】:

      【解决方案2】:

      只需实现IEnumerable&lt;T&gt; 接口即可。无需实现IEnumerator&lt;T&gt;,除非您想在枚举器中做一些特殊的事情,而您的情况似乎不需要。

      public class Mapper<K,T> : IEnumerable<T> {
          public IEnumerator<T> GetEnumerator()
          {
              return KToTMap.Values.GetEnumerator();
          }
      }
      

      就是这样。

      【讨论】:

      • 我一开始就是这样做的,但后来意识到我想在这个对象上使用 for each 来获取值。
      • 在对象上使用 foreach 唯一的要求是它有一个返回的 publi GetEnumerator() 方法和 IEnumerator,该对象甚至不需要实现任何接口,但建议您确实实现了 IEnumerable 或 IEnumerable,你可以猜到为什么;)
      • 这就是我的想法,所以我的错误不在其他地方。谢谢你的安慰。
      【解决方案3】:

      CreateEnumerable() 返回一个实现GetEnumerator()IEnumerable

      public class EasyEnumerable : IEnumerable<int> {
      
          IEnumerable<int> CreateEnumerable() {
              yield return 123;
              yield return 456;
              for (int i = 0; i < 6; i++) {
                  yield return i;
              }//for
          }//method
      
          public IEnumerator<int> GetEnumerator() {
              return CreateEnumerable().GetEnumerator();
          }//method
      
          IEnumerator IEnumerable.GetEnumerator() {
              return CreateEnumerable().GetEnumerator();
          }//method
      
      }//class
      

      【讨论】:

        【解决方案4】:

        【讨论】:

          【解决方案5】:

          这是罗伯特·塞奇威克 (Robert Sedgewick) 的“算法(第 4 版)”一书中的一个示例。

          它是用java编写的,我基本上用C#重写了它。

          public class Stack<T> : IEnumerable<T>
          {
              private T[] array;
          
              public Stack(int n)
              {
                  array = new T[n];
              }
          
              public Stack()
              {
                  array = new T[16];
              }
          
              public void Push(T item)
              {
                  if (Count == array.Length)
                  {
                      Grow(array.Length * 2);
                  }
          
                  array[Count++] = item;
              }
          
              public T Pop()
              {
                  if (Count == array.Length/4)
                  {
                      Shrink(array.Length/2);
                  }
          
                  return array[--Count];
              }
          
              private void Grow(int size)
              {
                  var temp = array;
                  array = new T[size];
                  Array.Copy(temp, array, temp.Length);
              }
          
              private void Shrink(int size)
              {
                  Array temp = array;
                  array = new T[size];
                  Array.Copy(temp,0,array,0,size);
              }
          
              public int Count { get; private set; }
              public IEnumerator<T> GetEnumerator()
              {
                  return new ReverseArrayIterator(Count,array);
              }
          
              IEnumerator IEnumerable.GetEnumerator()
              {
                  return GetEnumerator();
              }
          
          
              // IEnumerator implementation
              private class ReverseArrayIterator : IEnumerator<T>
              {
                  private int i;
          
                  private readonly T[] array;
          
                  public ReverseArrayIterator(int count,T[] array)
                  {
                      i = count;
                      this.array = array;
                  }
          
                  public void Dispose()
                  {
          
                  }
          
                  public bool MoveNext()
                  {
                      return i > 0;
                  }
          
                  public void Reset()
                  {
          
                  }
          
                  public T Current { get { return array[--i]; } }
          
                  object IEnumerator.Current
                  {
                      get { return Current; }
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-02-15
            • 2016-01-09
            • 1970-01-01
            • 2011-10-18
            • 1970-01-01
            • 2021-09-21
            • 1970-01-01
            相关资源
            最近更新 更多