Запись пользовательского IEnumerator <T> с итераторами

Полагаю, вам нужно включить зависимость Robolectric в свой build.gradle, а также указать бегуна для теста:

@RunWith(RobolectricTestRunner.class)
class ExampleUnitTest {

. Я не знаю, почему эта информация не включена в документацию по Android.

12
задан Alexey Romanov 11 January 2009 в 08:49
поделиться

3 ответа

Почему Вы хотите записать класс итератора? Смысл блока итератора так, Вы не имеете к...

т.е.

public IEnumerator<T> GetEnumerator() {
    int position = 0; // state
    while(whatever) {
        position++;
        yield return ...something...;
    }
}

Если Вы добавляете больше контекста (я, e, почему вышеупомянутое не может работать), мы можем, вероятно, помочь больше.

Но, если возможно, постарайтесь не писать класс итератора. Они - большая работа, и легкий понять превратно.

Между прочим, Вы не должны действительно беспокоиться Reset - это в основном удерживается от использования и никогда не должно действительно использоваться (так как на это нельзя положиться для работы на произвольный перечислитель).

Если Вы хотите использовать внутренний итератор, который прекрасен также:

int position = 0;
foreach(var item in source) {
   position++;
   yield return position;
}

или если у Вас только есть перечислитель:

while(iter.MoveNext()) {
   position++;
   yield return iter.Current;
}

Вы могли бы также рассмотреть добавление состояния (как кортеж) к вещи, к которой Вы приводите:

class MyState<T> {
    public int Position {get;private set;}
    public T Current {get;private set;}
    public MyState(int position, T current) {...} // assign
}
...
yield return new MyState<Foo>(position, item);

Наконец, Вы могли использовать подход расширения/делегата LINQ-стиля, с Action<int,T> предоставить положение и оценить вызывающей стороне:

    static void Main() {
        var values = new[] { "a", "b", "c" };
        values.ForEach((pos, s) => Console.WriteLine("{0}: {1}", pos, s));            
    }
    static void ForEach<T>(
            this IEnumerable<T> source,
            Action<int, T> action) {
        if (source == null) throw new ArgumentNullException("source");
        if (action == null) throw new ArgumentNullException("action");

        int position = 0;
        foreach (T item in source) {
            action(position++, item);
        }
    }

Выводы:

0: a
1: b
2: c
32
ответ дан 2 December 2019 в 04:09
поделиться

Я должен был бы согласиться с Marc здесь. Любая запись класс перечислителя полностью самостоятельно, если Вы действительно хотите к (просто, потому что Вы можете?) или просто используют interator блок и операторы урожая и делаются с ним. Лично, я никогда не касаюсь классов перечислителя снова.;-)

2
ответ дан 2 December 2019 в 04:09
поделиться

@Marc Gravell

Но, если возможно, постарайтесь не писать класс итератора. Они - большая работа, и легкий понять превратно.

Это точно, почему я хочу использовать yield оборудование в моем итераторе, чтобы сделать тяжелый подъем.

Вы могли бы также рассмотреть добавление состояния (как кортеж) к вещи, к которой Вы приводите:

Да, это работает. Однако это - дополнительное выделение на каждом шаге. Если я интересуюсь только T на большинстве шагов это - издержки, в которых я не нуждаюсь, если я могу избежать его.

Однако Ваше последнее предложение дало мне общее представление:

public IEnumerator<T> GetEnumerator(Action<T, int> action) {
    int position = 0; // state
    while(whatever) {
        position++;
        var t = ...something...;
        action(t, position);
        yield return t;
    }
}

public IEnumerator<T> GetEnumerator() {
    return GetEnumerator(DoNothing<T, int>());
}
1
ответ дан 2 December 2019 в 04:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: