IEnumerable来自IEnumerator

我已经写过关于自定义IEnumerator 。 什么是从中获取IEnumerable最简单的方法? 理想的解决方案(一行代码)将是为了这个目的有一些类。 或者我必须创建自己的?

我会以相反的方式接近这个; 虽然你可以 (根据迈克P的优秀答案)包装一个调查员假装可以枚举,但有一些你不能真正做的事情 – 例如, 希望 (尽管,公平,不坚持)你可以从可枚举的,理想的孤立和可重复的方式获得多个枚举器。 所以,如果我这样做:

 Assert.AreEqual(sequence.Sum(), sequence.Sum()); 

但如果您将枚举器“欺骗”为可枚举,则第二个序列将为空。 或者,如果你并行执行 – 只是奇怪的。 并且有一些方法可以并行处理它们 – 考虑:

 Assert.IsTrue(sequence.SequenceEqual(sequence)); 

这可以使两个枚举器同时前进,所以如果你只有一个枚举器,你就会被打破。

枚举器上有一个重置,但这在很大程度上是一个设计错误,不应该使用(在规范中甚至是一个正式的要求,如果你调用迭代器块会引发exception)。

一个更好的(IMO)问题是“如何从枚举中获取枚举器”,在这种情况下,答案是“调用GetEnumerator(),并记住检查以处理迭代器” – 或者用更简单的术语“使用foreach ”。

遗憾的是,没有内置方法。 我有这个扩展方法,我经常使用:

 static IEnumerable Iterate(this IEnumerator iterator) { while (iterator.MoveNext()) yield return iterator.Current; } 

在我的C#utils集合中,我有:

 class Enumerable : IEnumerable { Func> factory; public Enumerable(Func> factory) { this.factory = factory; } public IEnumerator GetEnumerator() { return this.factory(); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } 

这需要一个IEnumerator工厂函数 ,它通常可以很容易地提供,而不是单个IEnumerator实例(在第一次迭代后产生错误的结果并打破IEnumerable的语义)。 这避免了Marc Gravell标记的问题并建立了完整的IEnumerable行为。

我这样使用它:

 IEnumerable GetFruits() { var arg1 = ... return new Enumerable(() => new FruitIterator(arg1, arg2, ...)); } 

很简单:

 class Enumerate : IEnumerable { private Enumerate IEnumerator it; public Enumerate(IEnumerator it) { this.it = it; } public IEnumerator GetEnumerator() { return this.it; } } 

这也允许用户调用IEnumerator.Reset()如果你给它的枚举器支持它。

我所做的是创建一个实现IEnumerator和IEnumerable的类。 使GetEnumerator()返回自己,你可以像平常一样迭代它。

 public class MyClassEnumerator : IEnumerator, IEnumerable { public MyClass Current { get; private set; } object IEnumerator.Current => Current; public void Reset() { ... } public bool MoveNext() { ... } public IEnumerator GetEnumerator() { return this; } IEnumerator IEnumerable.GetEnumerator() { return this; } public void Dispose() { ... } }