IEnumerable перечисляется при вызове метода или при перечислении ответа

1

Я хочу знать, что параметр IEnumerable для метода перечисляется при вызове метода или когда я перечисляю возврат метода, предполагая, что у нас есть следующий код:

IEnumerable<T> ProcessList(IEnumerable<T> list)
{
    foreach(var element in list)
    {
        yield return ProcessElement(element);
    }
}

Мне больше всего любопытно, как писать Where-Linq как расширения.

  • 0
    Вы можете узнать себя, поместив точку торможения в вашу петлю. Но мое лучшее предположение состоит в том, что оно перечисляется при перечислении результата.
  • 0
    Если вы хотите создать Linq-подобные методы расширения, вам стоит попробовать Edulinq от Jon Skeet.
Показать ещё 2 комментария
Теги:
ienumerable

2 ответа

4
Лучший ответ

list (enumerable) enumerable только после перечисления результата ProcessList (enum2):

static void Main(string[] args)
{
    var enumerable = Enum1();
    Console.WriteLine("Enum1 retrieved");
    var enum2 = Enum2(enumerable);
    Console.WriteLine("Enum2 called");
    foreach (var e in enum2)
    {
        Console.WriteLine(e);
    }
}

private static IEnumerable<string> Enum1()
{
    Console.WriteLine("Enum1");
    yield return "foo";
}

private static IEnumerable<string> Enum2(IEnumerable<string> enumerable)
{
    Console.WriteLine("Enum2");
    foreach (var s in enumerable)
    {
        yield return s;
    }
}

дает:

Enum1 retrieved
Enum2 called
Enum2
Enum1
foo

Последние три строки печатаются только при вводе циклы foreach.

1

Использование ключевого слова yield означает, что этот фрагмент кода будет оцениваться только по мере необходимости, чтобы предоставить результаты, которые вы используете. Другими словами, это не приведет к оценке:

var processed = ProcessList(unprocessed);

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

var processed = ProcessList(unprocessed).ToList();

это попросит его оценить IEnumerable, который заставит его запустить ваш код. Аналогично, если вы это сделаете:

var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
    DoSomething(x);
}

он будет запускать ваш метод ProcessElement() для каждого элемента по очереди. Для этого, если вы это сделаете:

var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
    DoSomething(x);
}

потому что вы используете только первые 10 элементов списка результатов, для них будет выполняться только ваш метод ProcessElement(). Остальные будут оцениваться только тогда, когда вы их используете.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню