当使用yield return时,GetEnumerator()方法会发生什么



学习集合以及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<string> name = sample.GetEnumerator();则它不会进入函数。我希望它进入函数,但不会返回任何内容,因为我还没有调用movenext()。当我指定收益率时会发生什么,使它以这种方式运行。该程序有效。

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

包含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;
}

最新更新