كيف يمكنك تنفيذ IEnumerator واجهة ؟
-
09-06-2019 - |
سؤال
لدي الدرجة التي خريطة الكائنات إلى كائنات ، ولكن على عكس القاموس أنه خرائط لهم في كلا الاتجاهين.أنا الآن في محاولة لتنفيذ مخصص واجهة 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();
}
}
المحلول
أولا ، لا تجعل مجموعتك كائن تنفيذ IEnumerator<>.وهذا يؤدي إلى الخلل.(النظر في الحالة التي يكون فيها اثنين من المواضيع بالتكرار على نفس المجموعة).
تنفيذ العداد بشكل صحيح تبين أن يكون غير تافهة ، لذلك C# 2.0 الخاصة إضافة دعم اللغة يفعل ذلك ، على أساس 'العائد return' البيان.
ريمون تشن الأخيرة في سلسلة من بلوق وظائف ("تنفيذ التكرار في C# و عواقبه") هو مكان جيد للحصول على ما يصل الى سرعة.
نصائح أخرى
مجرد تنفيذ واجهة IEnumerable لا تحتاج إلى تنفيذ IEnumerator إلا إذا كنت تريد أن تفعل بعض الأشياء الخاصة في العداد ، قضيتك لا يبدو أن تكون هناك حاجة.
public class Mapper<K,T> : IEnumerable<T> {
public IEnumerator<T> GetEnumerator()
{
return KToTMap.Values.GetEnumerator();
}
}
و هذا الأمر.
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
استخدام العائد العودة.
هنا مثال من كتاب "خوارزميات (4th Edition) روبرت Sedgewick".
كان مكتوب في جافا و أنا في الأساس أعاد كتابة ذلك في 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; }
}
}
}