延期执行并渴望评估 [英] Deferred execution and eager evaluation

查看:62
本文介绍了延期执行并渴望评估的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您能给我一个用C#进行急切评估的延迟执行的例子吗?

Could you please give me an example for Deferred execution with eager evaluation in C#?

我从MSDN上了解到,可以通过延迟评估或急切评估来实现LINQ中的延迟执行.我可以在互联网上找到通过延迟评估执行延迟执行的示例,但是找不到在通过渴望评估进行延迟执行的示例.

I read from MSDN that deferred execution in LINQ can be implemented either with lazy or eager evaluation. I could find examples in the internet for Deferred execution with lazy evaluation, however I could not find any example for Deferred execution with eager evaluation.

此外,延迟执行与惰性评估有何不同?在我看来,两者看起来都是一样的.您能为此提供任何示例吗?

Moreover, how deferred execution differs from lazy evaluation? In my point of view, both are looking same. Could you please provide any example for this too?

推荐答案

贝洛是我的回答,但也请注意,乔恩·斯凯特(Jon Skeet)今天在其博客上谈到了这一事实,这是关于他对MSDN的理解并不完全同意的事实,懒惰"作为MSDN并不清楚他们在

Bellow is my answer but also note that Jon Skeet spoke about it today on his blog an about the fact that he is not totally ok with the MSDN meaning of "Lazy" as MSDN isn't really clear of what lazy exactly mean when they use it in Just how lazy are you ? his post make for an interesting read.

另外 Wikipedia 假定应保留三个规则来进行懒惰评估,而第三点则不行在MSDN中受到尊重,因为如果再次调用GetEnumerator,表达式将被多次评估(通过规范Reset不能在使用yield关键字生成的枚举器对象上实现,并且大多数linq当前都使用它)

Additionally Wikipedia assume that three rules should be maintained for lazy evaluation and third point isn't respected in MSDN meaning as the expression will be evaluated more than once if GetEnumerator is called again (By the spec Reset is not implemented on enumerator objects generated using the yield keyword and most of linq use it currently)

考虑功能

int Computation(int index)

立即执行

IEnumerable<int> GetComputation(int maxIndex)
{
    var result = new int[maxIndex];
    for(int i = 0; i < maxIndex; i++)
    {
        result[i] = Computation(i);
    }
    return result;
}

  • 调用函数Computation时执行maxIndex
  • GetEnumerator返回枚举器的新实例,什么也不做.
  • 每次调用MoveNext时,将存储在下一个Array单元中的值放在IEnumeratorCurrent成员中,仅此而已.
    • When the function is called Computation is executed maxIndex times
    • GetEnumerator returns a new instance of the enumerator doing nothing more.
    • Each call to MoveNext put the the value stored in the next Array cell in the Current member of the IEnumerator and that's all.
    • 成本:预付款项较大,枚举时较小(仅副本)

      Cost: Big upfront, Small during enumeration (only a copy)

      IEnumerable<int> GetComputation(int maxIndex)
      {
          var result = new int[maxIndex];
          for(int i = 0; i < maxIndex; i++)
          {
              result[i] = Computation(i);
          }
          foreach(var value in result)
          {
              yield return value;
          }
      }
      

      • 调用该函数时,将创建实现IEnumerable的自动生成类的实例(在规范中称为可枚举对象"),并将自变量(maxIndex)的副本存储在其中.
      • GetEnumerator返回枚举器的新实例,什么也不做.
      • 第一次调用MoveNext会执行maxIndex乘以计算方法,然后将结果存储在数组中,然后Current将返回第一个值.
      • 每次对MoveNext的调用都会在Current中放入存储在数组中的值.
        • When the function is called an instance of an auto generated class (called "enumerable object" in the spec) implementing IEnumerable is created and a copy of the argument (maxIndex) is stored in it.
        • GetEnumerator returns a new instance of the enumerator doing nothing more.
        • The first call to MoveNext executes maxIndex times the compute method, store the result in an array and Current will return the first value.
        • Each subsequent call to MoveNext will put in Current a value stored in the array.
        • 费用:没有任何预付款,枚举开始时为大,枚举期间为小(仅副本)

          Cost: nothing upfront, Big when the enumeration start, Small during enumeration (only a copy)

          IEnumerable<int> GetComputation(int maxIndex)
          {
              for(int i = 0; i < maxIndex; i++)
              {
                  yield return Computation(i);
              }
          }
          

          • 调用该函数时,会发生与延迟执行情况相同的事情.
          • GetEnumerator返回枚举器的新实例,什么也不做.
          • 每次对MoveNext的调用都执行一次Computation代码,将值放入Current中,然后让调用者立即对结果进行操作.
            • When the function is called the same thing as the lazy execution case happens.
            • GetEnumerator returns a new instance of the enumerator doing nothing more.
            • Each call to MoveNext execute once the Computation code, put the value in Current and let the caller immediately act on the result.
            • 大多数linq使用延迟执行和延迟执行,但是某些功能不能像排序那样.

              Most of linq use deferred and lazy execution but some functions can't be so like sorting.

              成本:无所事事,枚举期间中等(在此执行计算)

              Cost: nothing upfront, Moderate during enumeration (the computation is executed there)

              • 立即表示在函数中完成计算/执行,并在函数返回后立即完成. (与大多数C#代码一样,完全急切评估)
              • Deferred/渴望意味着大部分工作将在第一个MoveNext上完成或创建IEnumerator实例时(对于IEnumerable是调用GetEnumerator时)
              • Deferred/ Lazy 意味着每次调用MoveNext时都会完成工作,但是以前没事.
              • Immediate mean that the computation/execution is done in the function and finished once the function return. (Fully eager evaluation as most C# code does)
              • Deferred/Eager mean that most of the work will be done on the first MoveNext or when the IEnumerator instance is created (For IEnumerable it is when GetEnumerator is called)
              • Deferred/Lazy mean that the work will be done each time MoveNext is called but nothing before.

              并行LINQ 的处理方式略有不同,因为可以认为计算从从调用者的角度出发,但在内部,枚举一开始就并行地开始计算某些元素.结果是,如果下一个值已经存在,您将立即获得它,否则必须等待它.

              Parallel LINQ does it a little differently as the computation could be considered deferred/Lazy from the point of view of the caller but internally the computation of some number of elements begin in parallel as soon as the enumeration begin. The result is that if the next value is already there you get it immediately but otherwise you will have to wait for it.

              这篇关于延期执行并渴望评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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