C#:如何翻译Yield关键字

时间:2011-01-13 16:59:29

标签: c# yield

  1. 如果没有 yield 关键字,MSDN示例会是什么样子?如果您愿意,可以使用任何示例。我只想了解幕后发生了什么。
  2. 产量运算符急切懒惰评估?
  3. 示例:

    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);
            }
        }
    }
    

    如果热切评估收益率算子,我的猜测是:

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

    我不知道如果对yield运算符进行延迟计算,它会是什么样子。

    更新: 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;
    }
    

4 个答案:

答案 0 :(得分:11)

首先,yield不是运算符。 yield return和yield break是语句

有很多关于编译器如何实现迭代器块的文章。从迭代器块上的读取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/

答案 1 :(得分: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;
    }
  }
}

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

答案 2 :(得分:0)

  1. 这将是IEnumerable<T>的自定义实现,而不是依赖于List<T>
  2. 等现有实现
  3. 懒洋洋。
  4. 有关详情here

答案 3 :(得分:0)

  1. .NET Reflector反编译它。它是一个通用的解决方案(实际上是状态机),但非常复杂,&gt;如果我没记错的话会有20行代码。
  2. 懒惰。这就是yield非常有效的原因。