Как foreach работает когда цикличное выполнение через функциональные результаты?

бойтесь моего google-fu

$pdo = new PDO(
    'mysql:host=mysql.example.com;dbname=example_db',
    "username",
    "password",
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

первый хит;)

31
задан Adam Lear 27 October 2009 в 18:36
поделиться

3 ответа

Функция вызывается только один раз, чтобы вернуть IEnumerator ; после этого для перебора результатов используются метод MoveNext () и свойство Current :

foreach (Foo f in GetFoos())
{
    // Do stuff
}

в некоторой степени эквивалентно:

using (IEnumerator<Foo> iterator = GetFoos().GetEnumerator())
{
    while (iterator.MoveNext())
    {
        Foo f = iterator.Current;
        // Do stuff
    }
}

Обратите внимание, что итератор расположен в конец - это особенно важно для удаления ресурсов из блоков итератора, например:

public IEnumerable<string> GetLines(string file)
{
    using (TextReader reader = File.OpenText(file))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

В приведенном выше коде вы действительно хотите, чтобы файл был закрыт, когда вы закончите итерацию, и компилятор хитро реализует IDisposable , чтобы заставить это работать.

48
ответ дан 27 November 2019 в 21:58
поделиться

Нет .. функция будет вызвана один раз для получения IEnumerable .. а затем будет повторный вызов MoveNext и Current.

18
ответ дан 27 November 2019 в 21:58
поделиться

GetMyStrings () перенастраивает объект типа IEnumerable. Среда выполнения знает, как с этим бороться. Он вызывает IEnumerable.GetEnumerator (), а затем для этого объекта перечислителя вызывает MoveNext () и Current.

3
ответ дан 27 November 2019 в 21:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: