如果你想得到一个IEnumerator<T>
并得到一个IEnumerable<T>
代表序列的其余部分,从字面上看,你将不得不做一些魔法才能到达那里。
这样做的原因是,在一般意义上,一个可枚举可以被枚举多次,而一个枚举器不能,它本身只是那些“多次”中的一个。
首先,您可以尝试找出您正在处理的集合类型,从而在原始枚举器的其余部分之上返回一个适当的枚举器。你去的原因。
或者...您可以将其余的枚举数缓存到一个新集合中并返回它。这当然会消耗您的原始枚举器,无论在时间或内存方面可能是什么,并且可能是昂贵的。
或者......你可以按照几个人的建议去做,实际上不要返回枚举数,而是使用可枚举类的 Skip 和 Take 方法来返回你想要的。这将返回一个新的 enumerable,每次枚举时,它将枚举原始 enumerable,跳过前两项,并产生其余项。
让我改写最后一段。如果您不尝试将其余的IEnumerator<T>
作为新的枚举返回,而是只处理原始集合,则处理起来会容易得多。
这是一些缓存元素的代码。这样做的好处是,如果您从生成的可枚举中生成 2 个或更多枚举数(甚至只有 1 个),然后让可枚举超出范围,当枚举数开始在元素中移动时,它将允许垃圾收集器启动收集经过的元素。
换句话说,如果你这样做:
var enumerable = enumerator.Remaining();
var enumerator1 = enumerable.GetEnumerator();
var enumerator2 = enumerable.GetEnumerator();
enumerator1.MoveNext();
enumerator2.MoveNext();
<-- at this point, enumerable is no longer used, and the first (head) element
of the enumerable is no longer needed (there's no way to get to it)
it can be garbage collected.
当然,如果你保留 enumerable 并枚举其中的所有元素,它将生成原始 enumerable 中所有元素的内存副本,正如我所说,这可能会很昂贵。
无论如何,这是代码。它不是线程安全的:
using System;
using System.Collections.Generic;
using System.Collections;
namespace SO2829956
{
public class EnumeratorEnumerable<T> : IEnumerable<T>
{
private class Node
{
public T Value;
public Node Next;
}
private class Enumerator : IEnumerator<T>
{
private IEnumerator<T> _Enumerator;
private Node _Current;
public Enumerator(IEnumerator<T> enumerator, Node headElement)
{
_Enumerator = enumerator;
_Current = headElement;
}
public T Current
{
get { return _Current.Value; }
}
public void Dispose()
{
_Enumerator.Dispose();
}
object IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
if (_Current.Next != null)
{
_Current = _Current.Next;
return true;
}
else if (_Enumerator.MoveNext())
{
_Current.Next = new Node
{
Value = _Enumerator.Current
};
_Current = _Current.Next;
return true;
}
else
{
_Enumerator.Dispose();
return false;
}
}
public void Reset()
{
throw new NotImplementedException();
}
}
private IEnumerator<T> _Enumerator;
private Node _FirstElement;
public EnumeratorEnumerable(IEnumerator<T> enumerator)
{
_Enumerator = enumerator;
_FirstElement = new Node
{
Next = null,
Value = enumerator.Current
};
}
public IEnumerator<T> GetEnumerator()
{
return new Enumerator(_Enumerator, _FirstElement);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static class EnumeratorExtensions
{
public static IEnumerable<T> Remaining<T>(
this IEnumerator<T> enumerator)
{
return new EnumeratorEnumerable<T>(enumerator);
}
}
class Program
{
static void Main(string[] args)
{
List<int> values = new List<int> { 1, 2, 3, 4, 5 };
IEnumerator<int> enumerator = values.GetEnumerator();
enumerator.MoveNext();
enumerator.MoveNext();
var enumerable = enumerator.Remaining();
foreach (var i in enumerable)
Console.Out.WriteLine(i);
foreach (var i in enumerable)
Console.Out.WriteLine(i);
}
}
}
运行这个程序的输出是:
3
4
5
3
4
5