C# 2 и VB.Net 8 ввели новую возможность, названную iterators, которые были разработаны, чтобы помочь возвратить enumerables и счетчики.
Однако iterators - на самом деле ограниченная форма сопрограмм и могут использоваться, чтобы сделать много полезных вещей, которые не имеют никакого отношения к коллекциям объектов.
Какое нестандартное использование iterators Вы видели в реальном кодексе?
Я использовал их для написания системы в ASP.NET для создания серии связанных взаимодействий страницы. Если вы представляете разговор пользователя с веб-сайтом как серию запросов и ответов, вы можете моделировать взаимодействие как IENumerable
. Концептуально, как это;
IEnumerable<PageResponse> SignupProcess(FormValues form)
{
// signup starts with a welcome page, asking
// the user to accept the license.
yield return new WelcomePageResponse();
// if they don't accept the terms, direct
// them to a 'thanks anyway' screen
if (!form["userAcceptsTerms"])
{
yield return new ThanksForYourTimePageResponse();
yield break;
}
// On the second page, we gather their email;
yield new EmailCapturePage("");
while(!IsValid(form["address"]))
{
// loop until we get a valid address.
yield return new EmailCapturePage("The email address is incorrect. Please fix.");
}
}
Вы можете хранить итератор в состоянии сеанса, так что, когда пользователь возвращается на сайт, вы просто вытащите итератор, переместите итератор на следующую страницу и дайте его обратно для рендеринга. Сложные взаимодействия сайта кодируются в одном месте.
Я написал эту функцию, прежде чем узнать о ленивом операторе доходности. Это рекурсивно строит массивный итератор и возвращает его. Это не совсем эффективно, но я думаю, что это умно.
static member generatePrimeNumbers max =
let rec generate number numberSequence =
if number * number > max then numberSequence else
let filteredNumbers = numberSequence |> Seq.filter (fun v -> v = number || v % number <> 0L)
let newNumberSequence = seq { for i in filteredNumbers -> i }
let newNumber = newNumberSequence |> Seq.find (fun x -> x > number)
generate newNumber newNumberSequence
generate 2L (seq { for i in 2L..max -> i })
Для начала:
WebAction
s, которые вызывают обратно в перечислитель, когда он готов. (Обычно, когда документ завершает загрузку). Я использовал его для рекурсивного перебора файлов, содержащихся в папке, ее подпапках и так далее. Для каждого файла мне нужно было выполнить определенное действие. Рекурсивная функция с операторами yield return была простой для понимания всех остальных.