聪明地使用.Net 2迭代器

时间:2010-01-22 00:27:10

标签: c# .net vb.net iterator

C#2和VB.Net 8引入了一个名为iterators的新功能,旨在使返回枚举数和枚举数变得更容易。

但是,迭代器实际上是coroutines的有限形式,可以用来做许多与对象集合无关的有用的东西。

您在实际代码中看到了什么非标准的迭代器用法?

5 个答案:

答案 0 :(得分: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.");
   } 
}

您可以将迭代器存储在会话状态中,这样当用户返回到站点时,您只需将迭代器拉出,将迭代器移动到下一页,然后将其返回以进行渲染。复杂的网站互动在一个地方进行编码。

答案 1 :(得分:8)

开始时:

  • Jeffrey Richter使用迭代器编写了一个名为AsyncEnumerator的强大线程系统。它在MSDN杂志中描述,部分onetwo
  • Iterators也可用于等待方法中的UI交互,而不会阻止UI线程,正如我所描述的here
  • 以类似的方式,我使用迭代器创建一个基于IE的Web scraper,使用抓取方法返回WebAction的IEnumerators,它们在准备好时回调到枚举器中。 (通常,当文档完成加载时) 如果有兴趣的话,我可以在这里发帖。

答案 2 :(得分:1)

我用它来递归迭代文件夹,子文件夹等中包含的文件。对于我必须执行特定操作的每个文件。具有“收益率返回”语句的递归函数对于每个人的其他理解都很简单。

答案 3 :(得分:0)

在我发现lazy yield运算符之前,我写了这个函数。这递归地构建一个大型迭代器并返回它。它并不完全有效,但我认为它很聪明。

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

答案 4 :(得分: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;
        }
    }
}