【问题标题】:What happens to GetEnumerator() method when yield return is used?使用 yield return 时 GetEnumerator() 方法会发生什么?
【发布时间】:2013-08-01 09:56:23
【问题描述】:

学习集合和 IEnumerable 和 IEnumerator 接口。 我有以下程序。当我踏入

IEnumerator<string> name = sample.GetEnumerator();

它调用Console.WriteLine("inside getenumerator");

class Program
    {
        static void Main(string[] args)
        {
            SampleStrings sample = new SampleStrings();
            IEnumerator<string> name = sample.GetEnumerator();
            foreach (var item in sample)
            {
                Console.WriteLine(item);
            }
            Console.ReadLine();
        }
    }
    class SampleStrings : IEnumerable<string>
    {
        public IEnumerator<string> GetEnumerator()
        {
            Console.WriteLine("inside getenumerator");

            return null;//for testing purpose only
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }

现在,如果我在相同 IEnumerator&lt;string&gt; name = sample.GetEnumerator(); 时替换 GetEnumerator 如下 被调用然后它不会进入函数。我希望它能够进入函数但不返回任何内容,因为我还没有调用movenext()。 当我指定让它以这种方式运行的 yield 时会发生什么。该程序有效。

public IEnumerator<string> GetEnumerator()
        {
            Console.WriteLine("inside getenumerator");
            yield return "First";
            yield return "Second";

        }

【问题讨论】:

  • 您的“之前”代码无法编译(您不能将 "Test" 作为返回类型为 IEnumerator&lt;string&gt; 的函数的返回值)
  • @AakashM:更新了代码。之前的代码只是为了检查功能。我并没有真正使用返回值。我的问题清楚吗。我知道这有点棘手。

标签: c# collections enumerator yield-return


【解决方案1】:

包含yieldIEnumerator 的代码被转换为两部分。

创建了一个新的IEnumerator 类,其中包含您的原始代码,尽管已重写以便它按您期望的方式执行。 这是您的原始代码,包括 Console.WriteLine 所在的位置。

GetEnumerator() 方法包含全新生成的代码,它简单地实例化上面定义的 IEnumerator 并返回它。

因此,在调用第一个 MoveNext() 之前,您的任何代码都不会运行。

这就是为什么您经常会看到以下模式,例如立即执行参数验证。实现分为两部分:普通方法和包含yield的方法。

public IEnumerator<int> GetEnumerator(string whatever)
{
  // Perform validation immediately when called
  if (whatever == null) throw new ArgumentException();
  return GetEnumeratorInternal(whatever);
}

private IEnumerator<int> GetEnumeratorInternal(string whatever)
{
  // Everything in this method happens on first MoveNext
  yield return 1;
  yield return 2;
}

【讨论】:

  • 仍在消化答案。理解了一部分。
  • 您能否详细说明“GetEnumerator() 方法包含全新生成的代码,它只是实例化上面定义的 IEnumerator 并返回它。”声明。
  • 我的意思是:一旦编译,GetEnumerator() 方法不再匹配您的任何 C# 代码。它包含与return new GeneratedEnumeratorClass() 等效的内容。 您的生成器代码已编译为GeneratedEnumeratorClass.MoveNext()。这就是为什么当您调用生成器方法(使用yield 关键字的方法)时,这些代码都不会执行。它首先在第一次 MoveNext 调用期间执行。
猜你喜欢
  • 2011-02-08
  • 2012-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 2016-01-07
  • 2017-01-09
  • 2013-11-23
相关资源
最近更新 更多