只是想更好地理解这一点.我知道这是因为Deffered Execution
但究竟是什么原因导致该方法无法立即被调用.这是来自JonSkeet的EduLinq.
public static partial class Enumerable
{
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
foreach (TSource item in source)
{
if (predicate(item))
{
yield return item;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我使用它的地方.
List<int> list = new List<int>() { 1, 3, 4, 2, 8, 1 };
var s = list.Where(x => x > 4);
var result = s.ToList();
Run Code Online (Sandbox Code Playgroud)
我的问题是WhereIEnumerable上的静态方法为什么不在list.where()上调用它.但它在s.ToList()上调用.
我在Enumerable.Where()上有一个断点,它没有被击中s = list.Where(x => x > 4)但断点被击中s.ToList()
在我看到我的评论后,YUCK Why does LINQ have deferred execution?我将这个问题添加到了这个问题中.
请告诉我.
Where实际调用该方法,但它返回一个IEnumerable<T>.此返回值实际上是编译器为您实现的类.
请注意,您的实现使用迭代器(它包括yield return ...).当这种情况发生时,编译器周围改变你的方法,以便它创建一个编译器生成的类,并且,你居然迭代通过IEnumerable<T>,你写的代码得到执行.
第一次MoveNext调用时,第一次yield return执行代码将被执行.第二次通话将持续到下一次,等等.
调用ToList()整个枚举IEnumerable<T>,然后执行整个方法.
此外 - ToList()此处不需要执行您的代码.你可以使用foreach循环:
foreach(var val in s)
{
// Do something...
}
Run Code Online (Sandbox Code Playgroud)
甚至可以手动执行调用:
IEnumerable<int> s = list.Where(x => x > 4);
IEnumerator<int> sEnumerator = s.GetEnumerator(); // Get the enumerator
// This section will cause your code to run, but only until the *first* yield statement...
if (sEnumerator.MoveNext())
{
int val = sEnumerator.Current();
}
// Without further MoveNext() calls, you won't "finish" the foreach loop...
// This block will do one more "loop" in your foreach, going until the next "yield" (or the end of the method)
if (sEnumerator.MoveNext())
{
int val = sEnumerator.Current();
}
Run Code Online (Sandbox Code Playgroud)