Учитывая теги, я предполагаю, что вы имеете в виду в .NET - и я решу поговорить о C #, о чем я и знаю.
В операторе 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 C # in Depth , которую можно бесплатно загрузить. Вся глава 6 посвящена итераторам. У меня есть еще пара статей на моем сайте C # in Depth:
В качестве быстрого примера:
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 : 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
}
}