Таким образом, я думал, что понял, что С# yield return как во многом то же самое, что и урожай питонов, который, как я думал, я понял. Я думал, что компилятор преобразует функцию в объект с указателем на то, где выполнение должно быть возобновлено, и когда запрос на следующее значение приходит по объекту, запускается до следующего урока, где он обновляет указатель того, где возобновить выполнение и возвращает ценность.
В python это похоже на ленивую оценку, так как она генерирует значения по мере необходимости, но как только значения используются, когда они могут быть gc'ed, если не сохранять в другой переменной. Попытка итерации по результату такой функции дважды возвращает пустой итерабель, если вы не преобразуете ее в список.
ех.
def y():
list = [1,2,3,4]
for i in list:
yield str(i)
ys = y()
print "first ys:"
print ",".join(ys)
print "second ys:"
print ",".join(ys)
выходы
first ys:
1,2,3,4
second ys:
До недавнего времени я думал, что то же самое верно для С#, но попытка его в dotnetfiddle не удалась.
http://dotnetfiddle.net/W5Cbv6
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static IEnumerable<string> Y()
{
var list = new List<string> {"1","2","3","4","5"};
foreach(var i in list)
{
yield return i;
}
}
public static void Main()
{
var ys = Y();
Console.WriteLine("first ys");
Console.WriteLine(string.Join(",", ys));
Console.WriteLine("second ys");
Console.WriteLine(string.Join(",", ys));
}
}
выходы
first ys
1,2,3,4,5
second ys
1,2,3,4,5
Что здесь происходит? Это кеширование результата? Это не может быть прав, иначе File.ReadLines взорвется на огромные файлы? Это просто перезапуск функции сверху сверху?
Примечание. Я немного сомневаюсь в некоторой терминологии генераторов и сопрограмм, поэтому я пытался избежать маркировки.