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

ckv*_*ckv 4 c# collections enumerator yield-return

学习集合和IEnumerable和IEnumerator接口.我有以下程序.我什么时候进入

IEnumerator<string> name = sample.GetEnumerator();
Run Code Online (Sandbox Code Playgroud)

它称之为 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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在,如果我在IEnumerator<string> name = sample.GetEnumerator(); 调用相同内容时将GetEnumerator替换为如下所示,则它不会进入该函数.我希望它能进入这个功能,但不会返回任何东西,因为我还没有打电话movenext().当我指定使其以这种方式运行的产量时发生的事情.该计划有效.

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

        }
Run Code Online (Sandbox Code Playgroud)

jod*_*ods 8

IEnumerator包含的代码分为yield两部分.

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是:一旦编译,`GetEnumerator()`方法就不再匹配任何C#代码了.它包含的东西等同于`return new GeneratedEnumeratorClass()`._Your_生成器代码已编译成`GeneratedEnumeratorClass.MoveNext()`.这就是为什么当你调用一个生成器方法(使用`yield`关键字的方法)时,这些代码都不会执行.它首先在第一个`MoveNext`调用期间执行. (2认同)