2010-01-22 3 views
14

C# 2 и VB.Net 8 представили новую функцию под названием iterators, которая была разработана для облегчения возврата счетчиков и счетчиков.Умное использование .Net 2 итераторов

Однако итераторы на самом деле являются ограниченной формой coroutines и могут использоваться для создания множества полезных вещей, которые не имеют ничего общего с коллекциями объектов.

Какое нестандартное использование итераторов вы видели в реальном коде?

+0

Зачем ограничивать его C#? – ChaosPandion

+0

@Chaos: Я не понимал, что они также поддерживаются VB. Ред. – SLaks

+1

На самом деле, итераторные блоки вообще не являются «.NET» (значение: runtime). Это языковые функции, полностью обеспечиваемые компилятором. –

ответ

11

Я использовал их для написания системы в 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."); 
    } 
} 

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

+0

(Я исправил синтаксис 'yield') Мне очень нравится эта идея. Это было бы еще лучше с ASP.Net MVC, но для настройки может потребоваться несколько обманщиков. – SLaks

+0

Спасибо. Я подозреваю, что вы можете вырвать стандартную информацию о маршрутизации из MVC, но я думаю, что вы правы - это будет много работы. У меня также есть _no idea_, как бы я работал с асинхронными вызовами AJAX ... –

+0

Где бы вы разместили это между запросами страницы?На безгражданном кластерном сервере? Я не уверен, что все так замечательно, извините. –

8

Чтобы начать вещи:

  • Jeffrey Richter написал мощную систему многопоточности под названием AsyncEnumerator с помощью итераторов. Это описано в журнале MSDN, части one и two.
  • Итераторы также могут использоваться для ожидания взаимодействия пользовательского интерфейса в рамках метода без блокировки потока пользовательского интерфейса, как я описал here.
  • В том же ключе я использовал итераторы для создания веб-скребка на основе IE с методами скремблирования, которые возвращают IEnumerators WebAction, которые возвращаются в перечислитель при готовности. (Как правило, когда документ заканчивает загрузку).
    Если люди заинтересованы, я могу опубликовать его здесь.
0

Я написал эту функцию, прежде чем узнал о ленивом операторе. Это рекурсивно строит массивный итератор и возвращает его. Это не совсем эффективно, но я думаю, что это умно.

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 }) 
+0

На каком языке? F #? – SLaks

+0

Да, ключевое слово seq является псевдонимом для IEnumerable. – ChaosPandion

1

Я использовал его для рекурсивного перебора файлов, содержащихся в папке, ее подпапках и т. Д. Для каждого файла я должен был выполнить определенное действие. Рекурсивная функция с утверждениями «yield return» была простой для понимания другими людьми.

0

Rhino.ETL интенсивно использует его, чтобы объединить преобразования над последовательностью входных

, например, 3-х операций, которые могут быть объединены, повторно использовать

public IEnumerable<Row> Execute(IEnumerable<Row> rows) 
{ 
    foreach(var line in File.EnumerateLines()) 
    { 
     var row = new Row(); 
     row["key"] = int.Parse(line.Substring(1)); 
     yield return row; 
    } 
} 

public IEnumerable<Row> Execute(IEnumerable<Row> rows) 
{ 
    foreach(var row in rows) 
    { 
     var value = (int)row["key"]; 
     row["key"] = value + 2; 
     yield return row; 
    } 
} 

public IEnumerable<Row> Execute(IEnumerable<Row> rows) 
{ 
    using (var file = new Streamwriter(filename)) 
    { 
     foreach(var row in rows) 
     { 
      file.WriteLine(row["key"]); 
      yield return row; 
     } 
    } 
} 
Смежные вопросы