如何在没有yield语句的情况下实现Iterator模式(IEnumerator <t>)

时间:2018-05-12 08:50:33

标签: c# .net design-patterns ienumerator

如何在不使用Annotation-specified bean name 'queueHelper' for bean class [com.x.library.utils.QueueHelper] conflicts with existing, non-compatible bean definition of same name and class [com.x.document.utils.QueueHelper] 关键字的情况下重写GetEnumerator方法? 方法代码:

yield

我只知道如何手动实施。

1 个答案:

答案 0 :(得分:7)

实际上,yield语句是syntactic sugar,它使编译器实际生成一个实现IEnumerator<T>接口的类,并使用{{1}重写方法体。语句进入状态机。

每个状态都与最终生成序列中下一个元素的代码部分相关联。这嵌入在yield方法中。状态机可以表示所有必要的构造(序列,选择,迭代),因此所有C#代码(意味着方法中的语句)都可以像这样重写。这是潜在的魔法&#39; MoveNext()

在您的特定情况下,重写到状态机以及yield(及其继承的IEnumerator<T>(非通用)和IEnumerator接口)的相应完整实现将看起来像这样:

IDisposable

每次调用public class CustomEnumerator : IEnumerator<int> { public int Current { get; private set; } object IEnumerator.Current => this.Current; // internal 'position' in the sequence, i.e. the current state of the state machine private int position = 0; public bool MoveNext() { // advance to next state // (works for linear algorithms; an alternative is to select the next state at the end of processing the current state) position++; // perform the code associated with the current state and produce an element switch (position) { // state 1: line 'yield return 1;' case 1: Current = 1; return true; // state 2: lines 'Console.WriteLine("1");' and 'yield return 2;' case 2: Console.WriteLine("1"); // see also note at the end of this answer Current = 2; return true; // there are no other states in this state machine default: return false; } } public void Reset() { position = 0; } public void Dispose() { // nothing to do here } } ,这是MoveNext()语句的每次迭代内部发生的事情,会导致部分代码被执行 - 直到生成序列中的下一个元素。 / p>

为了使这个实现可用,相应的foreach实现是必要的,这是非常简单的:

IEnumerable<T>

然后,以下两个public class CustomEnumerable : IEnumerable<int> { public IEnumerator<int> GetEnumerator() { return new CustomEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } 循环将产生完全相同的结果:

foreach

注意:在您的void Main() { // custom implementation of IEnumerator<T> foreach (int i in new CustomEnumerable()) { Console.WriteLine(i); } // your original implementation—will produce same results // note: I assume someObject implements IEnumerable<T> and hence your GetEnumerator() method foreach (int i in someObject) { Console.WriteLine(i); } } 代码中,{/ 1}}之后的调用枚举数返回GetEnumerator()(并且调用者处理它),以便看起来有点奇怪。