Как бы вы реализовали интерфейс 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();
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
0
17 092
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Используйте доходность возврата.

Для чего используется ключевое слово yield в C#?

Просто реализуйте интерфейс IEnumerable, нет необходимости реализовывать IEnumerator, если вы не хотите делать какие-то особые вещи в перечислителе, которые в вашем случае, похоже, не нужны.

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

и это все.

Так я делал сначала, но позже понял, что хотел бы использовать для каждого в этом объекте, чтобы получить значения.

Tomas Pajonk 10.09.2008 17:28

для использования foreach с объектом единственное требование - наличие у него метода publi GetEnumerator (), который возвращает, и IEnumerator, объект даже не должен реализовывать какой-либо интерфейс, но рекомендуется реализовать IEnumerable или IEnumerable <T> , можете догадаться почему;)

Pop Catalin 10.09.2008 17:35

Я так думал, значит, моя ошибка где-то еще. Спасибо за заверение.

Tomas Pajonk 10.09.2008 17:39
Ответ принят как подходящий

Во-первых, не заставляйте свой объект коллекции реализовывать IEnumerator <>. Это приводит к ошибкам. (Рассмотрим ситуацию, когда два потока выполняют итерацию по одной и той же коллекции).

Правильная реализация перечислителя оказывается нетривиальной, поэтому в C# 2.0 для этого добавлена ​​поддержка специального языка на основе оператора yield return.

Недавняя серия сообщений в блоге Раймонда Чена («Реализация итераторов в C# и ее последствия») - хорошее место для ускорения.

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

Вот пример из книги Роберта Седжвика «Алгоритмы (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; }
        }
    }
}

Другие вопросы по теме