如何编写IEnumerator<T>需要维护某些状态的自定义实现,并仍然可以使用迭代器块来简化它?我能想到的最好的是这样的:
public class MyEnumerator<T> : IEnumerator<T> {
private IEnumerator<T> _enumerator;
public int Position {get; private set;} // or some other custom properties
public MyEnumerator() {
Position = 0;
_enumerator = MakeEnumerator();
}
private IEnumerator<T> MakeEnumerator() {
// yield return something depending on Position
}
public bool MoveNext() {
bool res = _enumerator.MoveNext();
if (res) Position++;
return res;
}
// delegate Reset and Current to _enumerator as well
}
public class MyCollection<T> : IEnumerable<T> {
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return GetEnumerator();
}
public MyEnumerator<T> GetEnumerator() {
return new MyEnumerator<T>();
}
...
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 32
你为什么要写一个迭代器类?迭代器块的重点是你不必......
即
public IEnumerator<T> GetEnumerator() {
int position = 0; // state
while(whatever) {
position++;
yield return ...something...;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你添加更多的上下文(即,为什么以上不能工作),我们可能会提供更多帮助.
但是如果可能的话,避免编写迭代器类.他们工作很多,容易出错.
顺便说一下,你真的不必费心Reset- 它在很大程度上已被弃用,并且不应该被使用(因为它不能依赖于任意枚举器).
如果你想使用内部迭代器,那也没关系:
int position = 0;
foreach(var item in source) {
position++;
yield return position;
}
Run Code Online (Sandbox Code Playgroud)
或者如果您只有一个枚举器:
while(iter.MoveNext()) {
position++;
yield return iter.Current;
}
Run Code Online (Sandbox Code Playgroud)
您也可以考虑将状态(作为元组)添加到您收益的事物中:
class MyState<T> {
public int Position {get;private set;}
public T Current {get;private set;}
public MyState(int position, T current) {...} // assign
}
...
yield return new MyState<Foo>(position, item);
Run Code Online (Sandbox Code Playgroud)
最后,您可以使用LINQ样式的扩展/委托方法,Action<int,T>并为调用者提供位置和值:
static void Main() {
var values = new[] { "a", "b", "c" };
values.ForEach((pos, s) => Console.WriteLine("{0}: {1}", pos, s));
}
static void ForEach<T>(
this IEnumerable<T> source,
Action<int, T> action) {
if (source == null) throw new ArgumentNullException("source");
if (action == null) throw new ArgumentNullException("action");
int position = 0;
foreach (T item in source) {
action(position++, item);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
0: a
1: b
2: c
Run Code Online (Sandbox Code Playgroud)