我有要求我必须以记录为后盾。所以我正在使用IEnumerator。但我可以通过movenext前进,但没有办法退回
答案 0 :(得分:13)
通过在IEnumerator<T>
中移动List<T>
中的内容,可以将public interface ITwoWayEnumerator<T> : IEnumerator<T>
{
bool MovePrevious();
}
public class TwoWayEnumerator<T> : ITwoWayEnumerator<T>
{
private IEnumerator<T> _enumerator;
private List<T> _buffer;
private int _index;
public TwoWayEnumerator(IEnumerator<T> enumerator)
{
if (enumerator == null)
throw new ArgumentNullException("enumerator");
_enumerator = enumerator;
_buffer = new List<T>();
_index = -1;
}
public bool MovePrevious()
{
if (_index <= 0)
{
return false;
}
--_index;
return true;
}
public bool MoveNext()
{
if (_index < _buffer.Count - 1)
{
++_index;
return true;
}
if (_enumerator.MoveNext())
{
_buffer.Add(_enumerator.Current);
++_index;
return true;
}
return false;
}
public T Current
{
get
{
if (_index < 0 || _index >= _buffer.Count)
throw new InvalidOperationException();
return _buffer[_index];
}
}
public void Reset()
{
_enumerator.Reset();
_buffer.Clear();
_index = -1;
}
public void Dispose()
{
_enumerator.Dispose();
}
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
}
包裹起来,这是一种方法:
public static class TwoWayEnumeratorHelper
{
public static ITwoWayEnumerator<T> GetTwoWayEnumerator<T>(this IEnumerable<T> source)
{
if (source == null)
throw new ArgumentNullExceptions("source");
return new TwoWayEnumerator<T>(source.GetEnumerator());
}
}
然后我会使用扩展方法公开这种枚举器:
T[]
请注意,如果您正在处理的集合已经是一个索引集合,例如List<T>
或{{1}},那么这绝对有点过分。对于诸如当您对尚未以方便索引的形式进行的序列进行枚举并且您希望能够向后以及向前的方式更有意义。
答案 1 :(得分:4)
IEnumerator
(和IEnumerator<T>
)接口仅实现仅转发枚举器。如果要允许通过集合进行双向迭代,则需要创建自己的类或接口。
答案 2 :(得分:2)
你无法使用IEnumerator向后退。要么将整个集合吸入List中,要么在每次循环中缓存当前元素,这样它就可以用于下一遍。