Как использовать ключевое слово foreach на пользовательских объектах в C # - PullRequest
18 голосов
/ 08 декабря 2008

Может ли кто-нибудь поделиться простым примером использования ключевого слова foreach с пользовательскими объектами?

Ответы [ 2 ]

41 голосов
/ 08 декабря 2008

Учитывая теги, я предполагаю, что вы имеете в виду в .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
    }
}
7 голосов
/ 08 декабря 2008

(я полагаю, C # здесь)

Если у вас есть список пользовательских объектов, вы можете просто использовать foreach так же, как и с любым другим объектом:

List<MyObject> myObjects = // something
foreach(MyObject myObject in myObjects)
{
     // Do something nifty here
}

Если вы хотите создать свой собственный контейнер, вы можете использовать ключевое слово yield (от .Net 2.0 и выше, я считаю) вместе с интерфейсом IEnumerable.

class MyContainer : IEnumerable<int>
{
    private int max = 0;
    public MyContainer(int max)
    {
        this.max = max;
    }

    public IEnumerator<int> GetEnumerator()
    {
        for(int i = 0; i < max; ++i)
            yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

А затем используйте его с foreach:

MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
    Console.WriteLine(i);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...