【问题标题】:Enumerators, iterators, IEnumerable - a bit confused枚举器、迭代器、IEnumerable - 有点困惑
【发布时间】:2011-07-31 06:09:48
【问题描述】:

我已通读C# 3.0 in a Nutshell 的迭代器/枚举器部分数次,但我仍然很难掌握它。从他们的名字来看,我最初的想法是 Iterator 会迭代一组 Enumerable 对象。我在正确的轨道上吗?如果是这样,那么常见的泛型集合呢,比如List<T>? List 在其某些操作期间是否创建/使用迭代器? T 是自动可枚举的吗?有演员表吗?一个甚至与另一个有什么关系吗?

在一些相关的说明中,在学习 MVC 时,我看到过这样的代码:

public Article GetArticle(int id)
{
    return _siteDB.Articles.SingleOrDefault(a => a.ArticleID == id);
}

public IEnumerable<Article> GetArticle(string title)
{
    return _siteDB.Articles.Where(a => a.Title.StartsWith(title)).AsEnumerable<Article>();
}

返回类型为IEnumerable&lt;T&gt; 会给我带来什么?


编辑:好的,我想我开始明白了。我的困惑仍然是迭代器。本书将它们描述为枚举器的生产者。我看不出yield return 实际发生在哪里。每个 yield 都会创建一个新的 Enumerator 吗?

【问题讨论】:

    标签: asp.net-mvc-2 iterator ienumerable enumerable


    【解决方案1】:

    类型 IEnumerable 为您提供 IEnumerable :) 它是一个接口定义方法GetEnumerator(),它返回IEnumerator。您可以根据需要多次调用该方法,并且始终获得 IEnumerator 的新实例。

    IEnumerator 具有属性 Current 和方法 MoveNext()Reset() 允许集合枚举。枚举本身可以通过调用 MoveNext() 来完成,如果之前调用 MoveNext() 返回 true,则读取 Current 属性。

    文档中有很好的实现和使用示例:http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx

    【讨论】:

    • 那么,枚举器会在 IEnumerable 对象上运行吗?枚举器与迭代器有何不同?它们似乎都在做同样的事情——依次遍历对象集合。
    • 没错,枚举器将在 IEnumerable 对象上运行。但在 C# 中,通常使用 foreach 而不是直接使用枚举器。
    • 正如不同答案所说,迭代器只是使用 yield 实现 IEnumerable 或 IEnumerator 接口的方式。 msdn.microsoft.com/en-us/library/dscyy5s0(v=vs.80).aspx
    • 好的,我想我看到了。谢谢!
    【解决方案2】:

    从它们的名字来看,我最初的想法是 Iterator 会迭代一组 Enumerable 对象。我在正确的轨道上吗?如果是这样,那么常见的泛型集合(例如 List)呢? List 在其某些操作期间是否创建/使用迭代器?

    iterator 是一种实现返回IEnumerable&lt;T&gt; 的方法的方法——它实际上是一个实现细节。不必创建一些自定义类来枚举集合,您可以使用迭代器来实现它,编译器会为您完成繁重的工作。

    返回类型为 IEnumerable 会给我带来什么?

    这基本上允许您枚举类型。例如,第二种方法(我个人称之为GetArticles)允许你写:

    foreach(var article in GetArticle(theTitle))
    {
       // Do something with article
    }
    

    【讨论】:

      【解决方案3】:

      让我看看我能不能回答这个问题。

      因此,List 实现了 IEnumerable,而不是必须实现它的 T,列表中的任何内容都可以迭代,例如使用 forech 或 for 循环。如果您使用像 List 这样的通用列表,这意味着您拥有的是 T 的列表,其中 T 是您定义的对象类型,这意味着您不必强制转换它,但另一方面您只能放置该列表中相同类型的对象。

      上面的代码可能意味着一系列的事情:

      1 - 任何实现 IEnumerable 的变量都可以保存 GetArticle 的结果, 例如:

      List yourList = GetArticle("test");
      Queue myQueue = GetArticle("test");
      

      2 - 查询的实际处理将被延迟。例如,如果您调用 Count,则在您调用该方法之后,这就是它实际执行/解决的时间。

      3 - 由于数字 2,如果您按照代码建议在数据库上执行此操作,那么您的连接必须保持打开状态,直到您使用该列表,否则您将收到异常。

      我想我已经回答了这些问题。

      【讨论】:

        猜你喜欢
        • 2014-01-09
        • 1970-01-01
        • 2017-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多