В чем разница между IEnumerator и IEnumerable?
Ответ Джейсона хорош, но я подумал, что просто добавлю свое мнение об этом.Представьте, что у вас есть последовательность:
1, 1, 2, 3, 5, 8, 13, ...
Теперь представьте, что у вас есть стрелка, указывающая на какую-то позицию этой последовательности:
1, 1, 2, 3, 5, 8, 13, ...
^
«Стрелка» - это объект, который может выполнять две вещи,Во-первых, он может дать вам то, на что он указывает.Во-вторых, он может указывать на следующее.
IEnumerator - это стрелка.У него есть свойство Current, которое дает вам то, на что оно указывает.У него есть метод MoveNext (), который указывает на следующую вещь.
Как вы получаете стрелу в первую очередь?Вам нужна фабрика стрел.Вы спрашиваете у фабрики стрелку, и она дает вам стрелку, которая указывает на первый элемент в последовательности.
IEnumerable является фабрикой стрелок.У него есть метод GetEnumerator, который дает вам стрелку для первого элемента последовательности.
Хорошим свойством этой схемы является то, что вы можете иметь несколько стрелок, указывающих на разные места в одной и той же последовательности.
Каковы преимущества реализации универсального интерфейса IEnumerable вместо просто IEnumerable?
Предположим, что последовательность состоит из целых чисел.Если вы реализуете IEnumerable
, тогда, когда вы говорите
foreach(int x in mysequence)
, на самом деле все, что нужно сделать, это преобразовать int в последовательности в объект, заключить в целое число, а затем сразу же распаковать объект обратно в целое, добавивсовершенно ненужное распределение памяти для каждой отдельной операции.Если компилятор знает, что последовательность состоит из целых чисел, он может пропустить ненужную операцию упаковки.
Предположим, что последовательность состоит из строк.Если вы реализуете IEnumerable<string>
, то вы можете сказать:
string first = mysequence.First();
Если вы этого не сделаете, то вы должны сказать
string first = (string)mysequence.First();
, что является ненужным и подверженным ошибкам.Вместо того, чтобы указывать компилятору через приведение, что тип является строкой, вы можете просто гарантировать , что тип является строкой, используя систему типов.