Comment voulez-vous mettre en œuvre l'interface IEnumerator?
-
09-06-2019 - |
Question
J'ai une classe que les objets de la carte des objets, mais à la différence de dictionnaire des cartes des deux façons.Je suis maintenant en train de mettre en œuvre une coutume interface IEnumerator qui parcourt les valeurs.
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();
}
}
La solution
Tout d'abord, ne pas faire de votre collection d'objet de mettre en œuvre IEnumerator<>.Cela conduit à des bugs.(Tenir compte de la situation où les deux fils sont itération au cours de la même collection).
Mise en œuvre d'un énumérateur correctement s'avère être non négligeable, de sorte que C# 2.0 ajouté spéciaux de soutien linguistique pour le faire, basé sur le "taux de retour" déclaration.
Raymond Chen récente série de billets de blog ("La mise en œuvre des itérateurs en C# et de ses conséquences") est un bon endroit pour obtenir jusqu'à la vitesse.
- Partie 1: http://blogs.msdn.com/oldnewthing/archive/2008/08/12/8849519.aspx
- Partie 2: http://blogs.msdn.com/oldnewthing/archive/2008/08/13/8854601.aspx
- Partie 3: http://blogs.msdn.com/oldnewthing/archive/2008/08/14/8862242.aspx
- Partie 4: http://blogs.msdn.com/oldnewthing/archive/2008/08/15/8868267.aspx
Autres conseils
Juste implémenter l'interface IEnumerable, pas besoin de mettre en œuvre le IEnumerator, sauf si vous voulez faire des choses spéciales à l'agent recenseur, qui pour votre cas ne semble pas être nécessaire.
public class Mapper<K,T> : IEnumerable<T> {
public IEnumerator<T> GetEnumerator()
{
return KToTMap.Values.GetEnumerator();
}
}
et c'est tout.
CreateEnumerable()
retourne un IEnumerable
qui met en œuvre 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
Utiliser les taux de retour.
Voici un exemple dans le livre "les Algorithmes (4e Édition) par Robert Sedgewick".
Il a été écrit en java et en gros, j'ai réécrit en 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; }
}
}
}