2008-09-10 19 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 <>を実装しないでください。これはバグにつながります。 (2つのスレッドが同じコレクションを反復している状況を考えてください)。

列挙子を正しく実装することは、自明ではないことが分かりました。そのため、C#2.0は「yield return」ステートメントに基づいて、特殊言語サポートを追加しました。

最新のブログ記事(「C#でのイテレータの実装とその結果」)は、スピードアップするのに適しています。

8

あなたが列挙子にいくつかの特別な事をする場合を除き、ちょうどあなたのケースのために必要とされていないようですこれは、のIEnumeratorを実装する必要がIEnumerableインターフェイスを実装していません。

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

それだけです。

+0

これは私が最初にやったやり方ですが、後でこのオブジェクトの値ごとに使いたいと思います。 –

+0

オブジェクトに対してforeachを使用する必要があるのは、IEnumeratorを返すpubli GetEnumerator()メソッドがあるだけで、オブジェクトはインターフェイスを実装する必要はありませんが、IEnumerableまたはIEnumerableを実装することをお勧めします、あなたは推測することができます;) –

+0

それは私が思ったので、私のエラーは他の場所です。安心していただきありがとうございます。 –

6

CreateEnumerable()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 
を実装 IEnumerableを返します
2

「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; } 
     } 
    } 
}