Возможно ли использование нескольких итераторов в c #? - PullRequest
1 голос
/ 18 ноября 2009

Можно ли использовать несколько итераторов (для одного класса или объекта) в c # .net? Если это так, приведите несколько простых примеров. Извините, если вопрос не понятен, пожалуйста, дайте мне понять.

Ответы [ 3 ]

7 голосов
/ 18 ноября 2009

Вы, конечно, можете создавать разные итераторы для обхода разными способами. Например, вы могли бы иметь:

public class Tree<T>
{
    public IEnumerable<T> IterateDepthFirst()
    {
        // Iterate, using yield return
        ...
    }

    public IEnumerable<T> IterateBreadthFirst()
    {
        // Iterate, using yield return
        ...
    }
}

Это то, о чем вы спрашивали?

Вы можете также потенциально написать:

public class Foo : IEnumerable<int>, IEnumerable<string>

но это вызовет много путаницы, и цикл foreach выберет тот, у кого был явно не реализованный вызов GetEnumerator.

Вы можете также повторять несколько раз для одной и той же коллекции одновременно:

foreach (Person person1 in party)
{
    foreach (Person person2 in party)
    {
        if (person1 != person2)
        {
            person1.SayHello(person2);
        }
    }
}
1 голос
/ 18 ноября 2009

Не совсем понятно, имеете ли вы в виду, что вы можете реализовать более одного итератора для класса, или если вы можете использовать более одного итератора для класса одновременно. Любой возможен.

У вас может быть столько итераторов, сколько вам нужно для класса:

public class OddEvenList<T> : List<T> {

  public IEnumerable<T> GetOddEnumerator() {
    return this.Where((x, i) => i % 2 == 0);
  }

  public IEnumerable<T> GetEvenEnumerator() {
    return this.Where((x, i) => i % 2 == 1);
  }

}

Вы можете иметь столько экземпляров итератора для активного класса одновременно, сколько вам нужно:

foreach (int x in list) {
  foreach (int y in list) {
    foreach (int z in list) {
      ...
    }
  }
}
0 голосов
/ 18 ноября 2009

Одним из вариантов будет реализация шаблона Стратегии:

  1. Создание отдельных классов IEnumerator для каждой стратегии обхода.
  2. Создать приватный атрибут в коллекции, в которой хранится текущая стратегия (по умолчанию).
  3. Создайте метод SetStrategy, который изменяет этот закрытый атрибут на выбранную конкретную стратегию.
  4. Переопределить GetEnumerator для возврата экземпляра текущей стратегии.

Конечно, это означает, что два потока, пытающихся установить стратегию одновременно, могут помешать, поэтому, если важно разделить коллекцию между потоками, это не лучшее решение.

Прямой паттерн Итератора также подойдет, что, как я полагаю, Джон Скит предлагает в своем первом примере, но вы теряете синтаксический сахар возможности использовать foreach.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...