延期执行并渴望评估 [英] Deferred execution and eager evaluation
问题描述
您能给我一个用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单元中的值放在IEnumerator
的Current
成员中,仅此而已. - When the function is called
Computation
is executedmaxIndex
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 theCurrent
member of theIEnumerator
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 andCurrent
will return the first value. - Each subsequent call to
MoveNext
will put inCurrent
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 theComputation
code, put the value inCurrent
and let the caller immediately act on the result. - 立即表示在函数中完成计算/执行,并在函数返回后立即完成. (与大多数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 theIEnumerator
instance is created (ForIEnumerable
it is whenGetEnumerator
is called) - Deferred/Lazy mean that the work will be done each time
MoveNext
is called but nothing before.
大多数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)
并行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屋!