Ответ 1
foreach
использует интерфейсы во многих случаях. Вам нужны интерфейсы, если вы хотите реализовать последовательность, которую затем может использовать foreach
. (Блоки Iterator обычно делают эту задачу реализации очень простой, хотя.)
Однако иногда бывает полезно использовать итераторы напрямую. Хорошим примером является попытка "соединить" две разные последовательности. Например, предположим, что вы получаете две последовательности - одно из имен, один из возрастов, и вы хотите напечатать их вместе. Вы можете написать:
static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages)
{
using (IEnumerator<int> ageIterator = ages.GetEnumerator())
{
foreach (string name in names)
{
if (!ageIterator.MoveNext())
{
throw new ArgumentException("Not enough ages");
}
Console.WriteLine("{0} is {1} years old", name, ageIterator.Current);
}
if (ageIterator.MoveNext())
{
throw new ArgumentException("Not enough names");
}
}
}
Также полезно использовать итератор, если вы хотите по-разному относиться к первому элементу:
public T Max<T>(IEnumerable<T> items)
{
Comparer<T> comparer = Comparer<T>.Default;
using (IEnumerator<T> iterator = items.GetEnumerator())
{
if (!iterator.MoveNext())
{
throw new InvalidOperationException("No elements");
}
T currentMax = iterator.Current;
// Now we've got an initial value, loop over the rest
while (iterator.MoveNext())
{
T candidate = iterator.Current;
if (comparer.Compare(candidate, currentMax) > 0)
{
currentMax = candidate;
}
}
return currentMax;
}
}
Теперь, если вас интересует разница между IEnumerator<T>
и IEnumerable<T>
, вы можете подумать об этом в терминах базы данных: подумайте о IEnumerable<T>
в качестве таблицы и IEnumerator<T>
в качестве курсора. Вы можете попросить таблицу дать вам новый курсор, и вы можете одновременно иметь несколько курсоров по одной и той же таблице.
Может потребоваться некоторое время, чтобы действительно понять это различие, но просто помню, что в списке (или массиве или что-то еще) нет понятия "где вы находитесь в списке", но итератор по этому списку/массиву/независимо от того, что этот бит состояния полезен.