В чем разница между FOREACH и итератором [дубликат]

138
24 июля 2019, 21:10

На данный вопрос уже ответили:

  • Работа цикла foreach, С# 1 ответ

Обьясните, пожалуйста, на простом примере, как работает итератор, зачем он нужен, если есть foreach и в чем их отличие. Читал доку https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/iterators - не понимаю в упор

Answer 1

foreach позволяет перебирать коллекции которые реализуют интерфейсы IEnumerable или IEnumerable от T, а также с объектами, которые такой интерфейс не реализуют, но ведут себя так, как будто реализуют. Вас, насколько я понял, интересует в первую очередь синтаксис yield return. Данный синтаксис ничего более, кроме как упрощение написания классов реализующих интерфейсы IEnumerable, IEnumerable от T или поведение аналогичное им. Давайте посмотрим два примера в которых будут возвращаться четные числа от 2 до 10. Первый будем реализовывать класс без yield return:

class MyCollection : IEnumerable<int>, IEnumerator<int>
{
    int _current = 0;
    public int Current
    {
        get
        {
            if (_current <= 10)
            {
                return _current;
            }
            throw new IndexOutOfRangeException();
        }
    }
    object IEnumerator.Current => Current;
    public bool MoveNext()
    {
        if (_current < 10)
        {
            _current += 2;
            return true;
        }
        return false;
    }
    public void Reset()
    {
        _current = 0;
    }
    public void Dispose()
    {
    }
    public IEnumerator<int> GetEnumerator()
    {
        return new MyCollection();
    }           
    IEnumerator IEnumerable.GetEnumerator()
    {
        return new MyCollection();
    }
}

Как видите, довольно сложно. Теперь второй пример, с yield retur. Поведение оставляем тоже самое, т.е. коллекция четных чисел от 2 до 10.

class MyCollection : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        for (int i = 2; i <= 10; i += 2)
        {
            yield return i;
        }
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Обратите внимание насколько уменьшился код и на то, что нам не пришлось реализовывать второй интерфейс, все это оказалось спрятано внутри синтаксического сахара yield return. При вызове вот такого кода, что для первого, что для второго примера:

static void Main(string[] args)
{
    foreach (var item in new MyCollection())
    {
        Console.WriteLine(item);
    }
    Console.ReadKey();
}

Вы увидите на консоли четные числа от 2 до 10. Как писать, выбирать вам.

READ ALSO
Синхронизация Progressbar с CMD

Синхронизация Progressbar с CMD

Мне нужно синхронизировать Progressbar в Windows Forms с командой sfc /scannowЭта команда отвечает за проверку системный файлов и идёт в процентах

140
Много процессов MySqld

Много процессов MySqld

Подскажите пожалуйста, откуда столько процессов MySqld?

120
Генерация ссылки на видео в youtube

Генерация ссылки на видео в youtube

Я знаком с php из далека, пока не претендую углубляться в него, но связь с сервером мне нужно, что-то элементарное передать, обработать, забрать...

115
PHP: пагинация странно себя ведёт

PHP: пагинация странно себя ведёт

Есть такой код вывода ссылок пагинации:

122