C # Itreator лучший подход - PullRequest
       20

C # Itreator лучший подход

0 голосов
/ 23 октября 2009

Помимо (IEnumerable возвращает GetEnumerator (), для "foreach" IEnumerble необходим)

почти следующие два подхода позволяют нам перебирать коллекцию. Что такое

преимущество одного над другим? (Я не спрашиваю разницу между IEnumerable и IEnumerator).

static void Main()
{
    IEnumerator<int> em = MyEnumerator<int>(new int[] { 1, 2, 3, 4 });
    IEnumerator<int> e = Collection<int>
                        (new int[] { 1, 2, 3, 4 }).GetEnumerator();

    while (em.MoveNext())
    {
        Console.WriteLine(em.Current);
    }

    while (e.MoveNext())
    {
        Console.WriteLine(e.Current);
    }
    Console.ReadKey(true);
}

подход 1

 public static IEnumerator<T> MyEnumerator<T>(T[] vals )

 {
     T[] some = vals;

     foreach (var v in some)
     {
       yield return v;
     }
}

заход на посадку 2

public static IEnumerable<T> Collection<T>(T[] vals)
     {
         T[] some = vals;

         foreach (var v in some)
         {
             yield return v;
         }
     }

Ответы [ 2 ]

1 голос
/ 23 октября 2009

Основным отличием является то, что большинство API поддерживают импульс IEnumerable<T>, но не IEnumerator<T>.

Вы также должны помнить, чтобы вызывать Reset () при его использовании, в то время как синтаксис более очевиден в IEnumerable<T> (просто снова вызовите GetEnumerator). Также см. Комментарий Эрика Липпера о том, что перезагрузка - плохая идея; если Reset не реализован в вашем IEnumerator<T> или содержит ошибки, он становится одноразовым перечислителем (в большинстве случаев довольно бесполезным).

Другое отличие может заключаться в том, что вы можете иметь IEnumerable<T>, который может быть перечислен из нескольких потоков одновременно, но IEnumerator<T> сохранит одну позицию в перечисленных данных (представьте RandomEnumerable или RangeEnumerable).

Итак, вывод состоит в том, что IEnumerable<T> более универсален, но в любом случае, если у вас есть функция, возвращающая IEnumerator<T>, генерирующая IEnumerable<T> вокруг нее, просто.

class EnumeratorWrapper<T> : IEnumerable<T>
{
    Func<IEnumerator<T>> m_generator;
    public EnumeratorWrapper(Func<IEnumerator<T>> generator)
    {
        m_generator = generator;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return m_generator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return m_generator();
    }
}

Просто для согласованности API использование IEnumerable<T> кажется лучшим решением для меня.

Но проблема с Reset() в IEnumerator<T> делает его в любом случае непригодным решением, поэтому IEnumerable<T> - это путь.

1 голос
/ 23 октября 2009

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

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