推迟执行和急切评估

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

我从MSDN读到,LINQ中的延迟执行可以通过懒惰或急切的评估来实现。 我可以在因特网上找到延迟执行的例子,但我找不到任何延迟执行的例子。

此外,延期执行与懒惰评估有何不同? 在我看来,两者看起来都一样。 你能提供任何例子吗?


贝娄是我的回答,但也注意到Jon Skeet今天在他的博客上谈到了这个事实,即他对MSDN的“懒惰”含义并不完全确定,因为MSDN并没有真正清楚他们使用时的懒惰究竟是什么意思它在你只是多么懒惰? 他的帖子让人感兴趣的阅读。

此外,维基百科假设应该为延迟评估维护三条规则,第三点在MSDN中不受尊重,因为如果再次调用GetEnumerator ,表达式将被多次评估(由于规范Reset未在使用yield关键字和linq的大部分目前使用它)


考虑一个函数

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将存储在下一个数组单元格中的值存储在IEnumeratorCurrent成员中,就这些了。
  • 成本 :在枚举期间大前期,小(仅限副本)

    延期但急切的执行

    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存储在数组中的值存入Current值。
  • 成本 :无预付款,枚举开始时为大,枚举期间为小(仅为副本)

    延期执行和延迟执行

    IEnumerable<int> GetComputation(int maxIndex)
    {
        for(int i = 0; i < maxIndex; i++)
        {
            yield return Computation(i);
        }
    }
    
  • 当这个函数被调用的时候,和懒惰的执行情况一样。
  • GetEnumerator返回一个新的枚举数实例。
  • 每次调用MoveNext执行一次Computation代码,将该值放入Current值并让调用者立即处理结果。
  • linq大部分使用延迟和懒惰执行,但一些函数不能像排序那样。

    成本 :无预付费,枚举期间中等(计算在那里执行)

    总结

  • 立即表示计算/执行在函数中完成,并在函数返回时完成。 (像大多数C#代码一样,完全热切的评估)
  • Deferred / Eager意味着大部分工作将在第一个MoveNext或创建IEnumerator实例时完成(对于IEnumerable它是在调用GetEnumerator时完成的)
  • 延迟/延迟意味着每次MoveNext都会完成该工作,但之前没有任何操作。
  • 并行LINQ做的有点不同,因为从调用者的角度来看,计算可以被认为是延迟/懒惰,但是一旦枚举开始,内部计算一些元素就会并行开始。 结果是,如果下一个值已经在那里,你立即得到它,否则你将不得不等待它。


    您可以急切地评估延迟执行IEnumerable的一种方法是使用linq的.ToArray()函数将其简单地转换为数组。

    var evaluated = enumerable.ToArray();
    

    这迫使完全枚举的评估,然后你有数组,你可以做任何你想要的。

    链接地址: http://www.djcxy.com/p/53705.html

    上一篇: Deferred execution and eager evaluation

    下一篇: Change amount scrollbar moves on a panel