C#:如何翻译Yield关键字

4 c# yield

  1. 没有yield关键字,MSDN示例会是什么样子?如果您愿意,可以使用任何示例.我只想了解幕后发生的事情.
  2. 产量运营商急切地懒洋洋地评估?

样品:

using System;
using System.Collections;
public class List
{
    public static IEnumerable Power(int number, int exponent)
    {
        int counter = 0;
        int result = 1;
        while (counter++ < exponent)
        {
            result = result * number;
            yield return result;
        }
    }

    static void Main()
    {
        // Display powers of 2 up to the exponent 8:
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果热切评估yield运算符,我的猜测是:

    public static IEnumerable Power(int number, int exponent)
    {
        int counter = 0;
        int result = 1;
        List<int> powers;
        while (counter++ < exponent)
        {
            result = result * number;
            powers.add(result);
        }
        return powers;
    }
Run Code Online (Sandbox Code Playgroud)

我不知道如果屈服运算符被懒惰地评估它会是什么样子.

更新: Reflector给出:

public class List
{
    // Methods
    public List();
    private static void Main();
    public static IEnumerable Power(int number, int exponent);

    // Nested Types
    [CompilerGenerated]
    private sealed class <Power>d__0 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
    {
        // Fields
        private int <>1__state;
        private object <>2__current;
        public int <>3__exponent;
        public int <>3__number;
        private int <>l__initialThreadId;
        public int <counter>5__1;
        public int <result>5__2;
        public int exponent;
        public int number;

        // Methods
        [DebuggerHidden]
        public <Power>d__0(int <>1__state);
        private bool MoveNext();
        [DebuggerHidden]
        IEnumerator<object> IEnumerable<object>.GetEnumerator();
        [DebuggerHidden]
        IEnumerator IEnumerable.GetEnumerator();
        [DebuggerHidden]
        void IEnumerator.Reset();
        void IDisposable.Dispose();

        // Properties
        object IEnumerator<object>.Current { [DebuggerHidden] get; }
        object IEnumerator.Current { [DebuggerHidden] get; }
    }
}

IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
    List.<Power>d__0 d__;
    if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
    {
        this.<>1__state = 0;
        d__ = this;
    }
    else
    {
        d__ = new List.<Power>d__0(0);
    }
    d__.number = this.<>3__number;
    d__.exponent = this.<>3__exponent;
    return d__;
}



private bool MoveNext()
{
    switch (this.<>1__state)
    {
        case 0:
            this.<>1__state = -1;
            this.<counter>5__1 = 0;
            this.<result>5__2 = 1;
            while (this.<counter>5__1++ < this.exponent)
            {
                this.<result>5__2 *= this.number;
                this.<>2__current = this.<result>5__2;
                this.<>1__state = 1;
                return true;
            Label_0065:
                this.<>1__state = -1;
            }
            break;

        case 1:
            goto Label_0065;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 11

首先,产量不是运营商.收益率和收益率突破是报表.

有很多关于编译器如何实现迭代器块的文章.首先阅读迭代器块上的C#规范部分; 它为C#的实现者如何想要它提供了一些建议.

接下来阅读Raymond Chen的系列文章"C#中迭代器的实现及其后果"

http://www.bing.com/search?q=raymond+chen+the+implementation+of+iterators

接下来,阅读Jon Skeet关于该主题的书籍章节:

http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx

如果您仍然感兴趣,那么请阅读我关于此功能的设计因素的系列:

http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/


Mar*_*dle 7

回到过去,在我们有yield运算符之前,我们曾经编写过实现IEnumerator的类.

class PowerEnumerator : IEnumerator<int>
{
  private int _number;
  private int _exponent;
  private int _current = 1;

  public PowerEnumerator(int number, int exponent)
  {
    _number = number;
    _exponent = exponent;
  }

  public bool MoveNext()
  {
    _current *= number;
    return _exponent-- > 0;
  }

  public int Current
  {
    get
    {
      if (_exponent < 0) throw new InvalidOperationException();
      return _current;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

或类似的东西.这不好玩,让我告诉你.

  • 显然我已经实现了通用版本,尽管它也没有.我们不得不在雪地里行走5英里才能开始建造.请注意,您可以以3.50英镑的价格享受一晚的夜晚,并且仍然有足够的变化来换取一袋芯片和一辆巴士回家. (2认同)