C# .NET2迭代器的巧妙使用

C# .NET2迭代器的巧妙使用,c#,.net,vb.net,iterator,C#,.net,Vb.net,Iterator,C#2和VB.NET8引入了一个名为的新特性,旨在使返回枚举数和枚举数更容易 然而,迭代器实际上是对象集合的一种有限形式,可以用来做许多与对象集合无关的有用的事情 您在实际代码中看到了迭代器的哪些非标准用法?首先: 使用迭代器编写了一个强大的线程系统AsyncEnumerator。MSDN杂志《零件和零件》对此进行了描述 迭代器还可以用于在方法内等待UI交互,而不阻塞UI线程,如我所述 类似地,我使用迭代器创建了一个基于IE的web scraper,使用scraping方法返回WebActio

C#2和VB.NET8引入了一个名为的新特性,旨在使返回枚举数和枚举数更容易

然而,迭代器实际上是对象集合的一种有限形式,可以用来做许多与对象集合无关的有用的事情

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

首先:

  • 使用迭代器编写了一个强大的线程系统AsyncEnumerator。MSDN杂志《零件和零件》对此进行了描述
  • 迭代器还可以用于在方法内等待UI交互,而不阻塞UI线程,如我所述
  • 类似地,我使用迭代器创建了一个基于IE的web scraper,使用scraping方法返回
    WebAction
    s的IEnumerator,当准备就绪时,这些IEnumerator会回调到枚举器中。(通常,当文档完成加载时)。
    如果有人感兴趣,我可以把它贴在这里

我使用它们在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.");
   } 
}
IEnumerable SignupProcess(FormValues表单)
{
//注册以欢迎页面开始,询问
//允许用户接受许可证。
产生返回新WelcomePageResponse();
//如果他们不接受条款,直接
//让他们进入“无论如何谢谢”屏幕
如果(!form[“userAcceptsTerms”])
{
返回新的ThanksForYourTimePageResponse();
屈服断裂;
}
//在第二页,我们收集他们的电子邮件;
生成新的EmailCapturePage(“”);
而(!IsValid(form[“address”]))
{
//循环直到我们得到一个有效的地址。
返回新的EmailCapturePage(“电子邮件地址不正确,请修复”);
} 
}

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

在我发现惰性屈服操作符之前,我编写了这个函数。这将递归地构建一个大型迭代器并返回它。这并不完全有效,但我认为它很聪明

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 })
静态成员generatePrimeNumbers max=
让rec生成数字序列=
如果编号*编号>最大值,则编号顺序为其他
让filteredNumbers=numberSequence |>Seq.filter(乐趣v->v=number | | v%number 0L)
让newNumberSequence=seq{for i in filteredNumbers->i}
让newNumber=newNumberSequence |>Seq.find(乐趣x->x>数字)
生成newNumber newNumberSequence
生成2L(seq{for i in 2L..max->i})

我使用它对文件夹中包含的文件及其子文件夹等进行递归迭代。对于每个文件,我必须执行特定的操作。带有“yield return”语句的递归函数对于其他人来说很简单。

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;
        }
    }
}
public IEnumerable执行(IEnumerable行)
{
foreach(文件.EnumerateLines()中的变量行)
{
var row=新行();
行[“键”]=int.Parse(行.子字符串(1));
收益返回行;
}
}
公共IEnumerable执行(IEnumerable行)
{
foreach(行中的变量行)
{
var值=(int)行[“键”];
行[“键”]=值+2;
收益返回行;
}
}
公共IEnumerable执行(IEnumerable行)
{
使用(var file=newstreamwriter(文件名))
{
foreach(行中的变量行)
{
file.WriteLine(行[“键]);
收益返回行;
}
}
}

@Chaos:我不知道它们也被VB支持。实际上,迭代器块根本不是“.NET”(意思是运行时)特性。它们是语言功能,完全由编译器提供。@Marc:是的,我知道,但我应该说什么?谢谢。我怀疑你可以从MVC中删除标准的路由内容,但我认为你是对的——这将是一项艰巨的工作。我也不知道如何处理异步AJAX调用…(我修复了你的
yield
语法)我非常喜欢这个想法。使用ASP.NETMVC会更好,但设置起来可能需要一些技巧。在页面请求之间,您会把它放在哪里?在无状态群集服务器上?对不起,我不确定这一切是否如此美妙。不,您不能在服务器场上运行它。我提到它是一个关于它的操作人员的古怪的例子,不一定是一个完全开发的web框架:)@Marc Gravell-你必须承认这很酷,即使它在某些硬件配置上不起作用。是的,seq关键字是IEnumerable的别名。