ito*_*son 20
不,这是不可能的.当C#编译器处理迭代器(包含yield语句的方法)时,编译器会生成一个实现IEnumerable和IEnumerator的类.生成的类的Reset实现只会抛出NotSupportedException.在当前版本的C#中无法影响这一点.
相反,您的调用代码将需要请求一个新的枚举器,即开始一个新的foreach循环.或者您需要放弃语言支持(yield语句)并编写自己的实现IEnumerator的类.
Tom*_*cek 10
没有内置支持,但您可以定义自己的实现IEnumerator,委托对C#生成的枚举器的所有方法调用,并且只允许您为Reset方法定义自己的行为.
该类的最简单版本如下所示:
class ResetableEnumerator<T> : IEnumerator<T>
{
public IEnumerator<T> Enumerator { get; set; }
public Func<IEnumerator<T>> ResetFunc { get; set; }
public T Current { get { return Enumerator.Current; } }
public void Dispose() { Enumerator.Dispose(); }
object IEnumerator.Current { get { return Current; } }
public bool MoveNext() { return Enumerator.MoveNext(); }
public void Reset() { Enumerator = ResetFunc(); }
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,ResetFunc您指定的返回一个new IEnumerator<T>,因此您提供的实现ResetFunc可以执行一些清理或重置时需要执行的任何操作,然后返回一个新的枚举器.
IEnumerator<int> Foo() { /* using yield return */ }
IEnumerator<int> PublicFoo() {
return new ResetableEnumerator<int> {
Enumerator = Foo(),
ResetFunc = () => {
Cleanup();
return Foo(); } };
}
Run Code Online (Sandbox Code Playgroud)
您需要将方法的所有原始局部变量存储Foo为类的字段,以便您可以访问它们Cleanup(注意,Foo在调用之后将永远不会执行正文的其余部分Reset),但这仍然比编写手写的迭代器!
我刚刚发现了一个很好的解决方法。让您的生成器方法返回IEnumerable,而不是 IEnumerator。然后你可以做
var values = MyGeneratorMethod();
var enumerator = values.GetEnumerator();
// ... do stuff with enumerator
enumerator = values.GetEnumerator(); // instead of enumerator.Reset();
Run Code Online (Sandbox Code Playgroud)
我相信 itowlson 的回答暗示了这个确切的技巧,但直到我在其他地方听说过这个技巧我才理解它。
| 归档时间: |
|
| 查看次数: |
4159 次 |
| 最近记录: |