Вопрос
Помимо (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;
}
}
Решение
Основное отличие состоит в том, что большинство API поддерживают импульс IEnumerable<T>
, но не IEnumerator<T>
.
Вы также должны помнить, чтобы вызывать Reset () при его использовании, в то время как синтаксис более очевиден в GetEnumerator
(просто позвоните RandomEnumerable
еще раз). Также см. Комментарий Эрика Липпера о том, что перезагрузка - плохая идея; если Reset не реализован в вашем RangeEnumerable
или содержит ошибки, он становится одноразовым перечислителем (во многих случаях довольно бесполезным).
Другое отличие может заключаться в том, что у вас может быть Reset()
, который может быть перечислен из нескольких потоков одновременно, но <=> хранить одну позицию в перечисленных данных (представьте себе <=> или <=>). р>
Таким образом, вывод заключается в том, что <=> более универсален, но в любом случае, если у вас есть функция, возвращающая <=>, генерирующую <=> вокруг нее, это просто.
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 и IEnumerator, и, поскольку вы специально сказали, что не спрашиваете разницу, оба хороши ...