В чем разница между IEnumerator и IEnumerable?
Ответ Джейсона хорош, но я думал, что просто добавлю, как я думаю об этом. Представьте, у вас есть последовательность:
1, 1, 2, 3, 5, 8, 13, ...
Теперь представьте себе, у вас есть стрелка, указывающая на какой-то позиции этой последовательности:
1, 1, 2, 3, 5, 8, 13, ...
^
An «стрелка» является объектом, который может сделать две вещи. Во-первых, он может дать вам то, на что он указывает. Во-вторых, он может указать на следующее.
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();
, который является ненужным и подверженным ошибкам. Вместо того, чтобы инструктировать компилятор с помощью приведения, что тип является строкой, вы можете просто гарантировать, что тип является строкой с использованием системы типов.
Я позволю john skeet ответить на этот вопрос –
@ Хасан: Я боюсь, что он сделает с вами, написав свое имя. – JYelton