Ответ 1
Учитывая теги, я предполагаю, что вы имеете в виду в .NET - и я буду говорить о С#, как о том, что знаю.
В заявлении foreach
(обычно) используются IEnumerable
и IEnumerator
или их общие кузены. Утверждение формы:
foreach (Foo element in source)
{
// Body
}
где source
реализует IEnumerable<Foo>
примерно эквивалентно:
using (IEnumerator<Foo> iterator = source.GetEnumerator())
{
Foo element;
while (iterator.MoveNext())
{
element = iterator.Current;
// Body
}
}
Обратите внимание, что IEnumerator<Foo>
располагается в конце, однако утверждение завершается. Это важно для блоков итератора.
Чтобы реализовать IEnumerable<T>
или IEnumerator<T>
самостоятельно, самый простой способ - использовать блок итератора. Вместо того, чтобы писать здесь все подробности, лучше всего просто отнести вас к главе 6 С# в глубине, которая является бесплатной загрузкой. Вся глава 6 посвящена итераторам. У меня есть еще несколько статей на моем сайте С# на глубине:
В качестве быстрого примера:
public IEnumerable<int> EvenNumbers0To10()
{
for (int i=0; i <= 10; i += 2)
{
yield return i;
}
}
// Later
foreach (int x in EvenNumbers0To10())
{
Console.WriteLine(x); // 0, 2, 4, 6, 8, 10
}
Чтобы реализовать IEnumerable<T>
для типа, вы можете сделать что-то вроде:
public class Foo implements IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
yield return "x";
yield return "y";
}
// Explicit interface implementation for nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator(); // Just return the generic version
}
}