2008-09-10 59 views
11

我有一個將對象映射到對象的類,但與字典不同,它將它們映射到兩個方向。我現在試圖實現一個自定義IEnumerator接口,通過值迭代。你將如何實現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(); 
    } 
} 

回答

18

首先,不要讓你的集合對象實現IEnumerator <>。這導致錯誤。 (考慮兩個線程迭代同一個集合的情況)。

實現一個枚舉器正確地證明是不平凡的,所以C#2.0基於'yield return'語句爲此添加了特殊語言支持。

Raymond Chen最近發表的一系列博客文章(「C#中迭代器的實現及其後果」)是一個很好的起步點。

8

,除非你想要做的枚舉一些特別的東西,這對於你的情況似乎並不需要就實現IEnumerable接口,無需實現IEnumerator。

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

就是這樣。

+0

這就是我一開始就這樣做的方式,但是後來才意識到我想用這個對象的每一個來獲得值。 – 2008-09-10 13:28:14

6

CreateEnumerable()返回IEnumerable它實現GetEnumerator()

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 
2

下面是由Robert Sedgewick編寫的「Algorithms(4th Edition)」一書的一個例子。

它是用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; } 
     } 
    } 
}