【问题标题】:Is there any difference between iterator methods returning IEnumerable<T> and IEnumerator<T>?返回 IEnumerable<T> 和 IEnumerator<T> 的迭代器方法之间有什么区别吗?
【发布时间】:2010-09-29 19:42:08
【问题描述】:

考虑两个具有相同主体的迭代器方法:

public static IEnumerable<int> It1() { 
    ...
}

public static IEnumerator<int> It2() { 
    ...
}

调用It2和调用It1.GetEnumerator()有什么不同的情况吗?

是否有充分的理由将迭代器定义为 IEnumerator&lt;T&gt; 而不是 IEnumerable&lt;T&gt;?我唯一能想到的就是当你在实现IEnumerable&lt;T&gt;.GetEnumerator()时。

编辑:迭代器方法是指使用yield returnyield break 构造的方法。

【问题讨论】:

  • 严格来说方法的实现不能相同。
  • 当然可以。 public static IEnumerable It1() { yield return 1; } 公共静态 IEnumerator It2() { 产量返回 1; }
  • 现在,编译器将它们转换成的内容明显不同;一个转换为实现 IEnumerator 的匿名类,另一个转换为实现 IEnumerable 和 IEnumerator 的两个匿名类。是否存在两个 IEnumerator 不同的情况?

标签: c# iterator


【解决方案1】:

如上所述,您不能将foreach 置于IEnumerator&lt;T&gt; 之上。因此,很难集成到代码中您想要迭代返回的内容的地方。

此外,这里的重要性在于 IEnumerable&lt;T&gt; 是一个工厂,因此您可以生成与 T 集合的实现不直接相关的 IEnumerator&lt;T&gt; 的实现。

现在更重要的是,LINQ 的所有扩展方法都在 IEnumerable&lt;T&gt; 上工作,因此您将希望通过返回它来使您的枚举尽可能易于使用。

【讨论】:

  • 是的,这就是更喜欢 IEnumerable 而不是 IEnumerator 的充分理由。这就是我问反方向的原因。
【解决方案2】:

如果您想负责编写 IEnumerable&lt;T&gt; 包装类,您可以这样做。

假设您有一个要无限枚举的类:

public class EveryDateInTheFuture : IEnumerable<DateTime>
{
    public EveryDateInTheFuture() { this.StartDate = DateTime.Today; }

    public DateTime StartDate { get; set; }

    public IEnumerator<DateTime> GetEnumerator()
    {
         while (true)
         {
             yield return date;
             date = date.AddDays(1);
         }
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-26
    • 2011-06-25
    • 1970-01-01
    • 2014-11-17
    • 2014-06-25
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多