C#中:如何翻译产量关键字 [英] C#: How to translate the Yield Keyword

查看:231
本文介绍了C#中:如何翻译产量关键字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  1. 会是什么样的MSDN示例的样子,而不在收益关键字?如果你perfer你可以使用任何的例子。我只是想了解什么是引擎盖下怎么回事。

  2. 是在收益操作符的热切懒洋洋地评估



示例:

 使用系统; System.Collections中使用
;
公共类List
{
公共静态IEnumerable的功率(INT编号,INT指数)
{
INT计数器= 0;
INT结果= 1;
,而(计数器++ LT;指数)
{
结果=结果*号;
产量返回结果;
}
}

静态无效的主要()
{
//显示2的幂高达指数8:
的foreach( INT I电力(2,8))
{
Console.Write({0},i)的;
}
}
}








如果屈服运营商急切这里评价是我的猜想:

 公共静态IEnumerable的功率(INT编号,INT指数)
{
INT计数器= 0;
INT结果= 1;
名单,LT; INT>权力;
,而(计数器++ LT;指数)
{
结果=结果*号;
powers.add(结果);
}
返回权力;
}



我不知道它是什么样子,如果收益率运算符懒洋洋地评估



更新:反射给出了这样的:

 公共类List 
{
//方法
公开名单();
私有静态无效的主要();
公共静态IEnumerable的功率(整型数字,诠释指数);

//嵌套类型
[编译器生成]
私人密封类<电力> d__0:IEnumerable的<对象> ;,的IEnumerable,IEnumerator的<对象> ;,的IEnumerator,IDisposable的
{
//字段
私人诠释<> 1__state;
私有对象<> 2__current;
公众诠释<> 3__exponent;
公众诠释<> 3__number;
私人诠释<> l__initialThreadId;
公众诠释<反向> 5__1;
公众诠释<&结果GT; 5__2;
公众诠释指数;
公众诠释号;

//方法
[DebuggerHidden]
公众与lt;电力> d__0(INT<> 1__state);
私人BOOL的MoveNext();
[DebuggerHidden]
&的IEnumerator LT;对象> IEnumerable的<对象> .GetEnumerator();
[DebuggerHidden]
的IEnumerator IEnumerable.GetEnumerator();
[DebuggerHidden]
无效IEnumerator.Reset();
无效IDisposable.Dispose();

//属性
对象的IEnumerator<对象> .Current {[DebuggerHidden]搞定; }
对象IEnumerator.Current {[DebuggerHidden]搞定; }
}
}

&的IEnumerator LT;对象> IEnumerable的<对象> .GetEnumerator()
{
列表与lt;电力> d__0 D__;
如果((Thread.CurrentThread.ManagedThreadId ==该<> l__initialThreadId)及及(该<> 1__state == -2))
{
本&所述;> 1__state = 0;
D__ =这一点;
}
,否则
{
D__ =新的List<电力和GT; d__0(0);
}
D __数=该<> 3__number;
D __指数=该<> 3__exponent;
返回D__;
}



私人BOOL的MoveNext()
{
开关(该<> 1__state)
{
的情况下0:
该<> 1__state = -1;
该<吧台和GT; 5__1 = 0;
该<&结果GT; 5__2 = 1;
,而(该<吧台和GT; 5__1 ++< this.exponent)
{
该<&结果GT; 5__2 * = this.number;
该<方式> 2__current =该<&结果GT; 5__2;
该<> 1__state = 1;
返回真;
Label_0065:
该<> 1__state = -1;
}
中断;

案例1:
转到Label_0065;
}
返回FALSE;
}


解决方案

回到过去的好时光,我们不得不屈服运营商之前,我们用来写一个实现了IEnumerator类

 类PowerEnumerator:IEnumerator的< INT> 
{
私人诠释_number;
私人诠释_exponent;
私人INT _current = 1;

公共PowerEnumerator(INT编号,INT指数)
{
_number =号;
_exponent =指数;
}

公共BOOL的MoveNext()
{
_current * =号;
返回_exponent--> 0;
}

公众诠释当前
{
得到
{
如果(_exponent℃下)抛出新的InvalidOperationException异常();
返回_current;
}
}
}

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


  1. What would the MSDN sample look like without the yield keyword? You may use any example if you perfer. I would just like to understand what is going on under the hood.
  2. Is the yield operator eagerly or lazily evaluated?

Sample:

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


If the yield operator is eagerly evaluated here is my guess:

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

I have no clue what it might look like if the yield operator is lazily evaluated.

Update: Reflector gives this:

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

解决方案

Back in the good old days, before we had the yield operator, we used to write classes which implemented 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;
    }
  }
}

Or something like that. It wasn't fun, let me tell you.

这篇关于C#中:如何翻译产量关键字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆