我正在阅读一本有关高级C#的书籍。此时,我正在阅读以下内容:
采用委托语法的Linq查询方法的幕后操作。
迄今为止,我已经了解了Where、Select、Skip、SkipWhile、Take、TakeWhile等方法。并且我还知道Lazy和Eager执行以及由其中一些方法返回的迭代器。
延迟执行是执行模型的一种模式,CLR确保只有在需要从IEnumerable-based信息源中提取值时才会提取该值。当任何Linq运算符使用延迟执行时,CLR将相关信息(如原始序列、谓词或选择器(如果有))封装到一个迭代器中,该迭代器将在使用ToList方法或ForEach方法或手动使用C#中的底层GetEnumerator和MoveNext方法从原始序列中提取信息时使用。
现在让我们看看以下两个例子:
当我设置断点并调试这两个语句时,我可以看到一个区别。
第一条语句:
第二条语句:
你能解释一下为什么吗?
采用委托语法的Linq查询方法的幕后操作。
迄今为止,我已经了解了Where、Select、Skip、SkipWhile、Take、TakeWhile等方法。并且我还知道Lazy和Eager执行以及由其中一些方法返回的迭代器。
延迟执行是执行模型的一种模式,CLR确保只有在需要从IEnumerable-based信息源中提取值时才会提取该值。当任何Linq运算符使用延迟执行时,CLR将相关信息(如原始序列、谓词或选择器(如果有))封装到一个迭代器中,该迭代器将在使用ToList方法或ForEach方法或手动使用C#中的底层GetEnumerator和MoveNext方法从原始序列中提取信息时使用。
现在让我们看看以下两个例子:
IList<int> series = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
// First example
series.Where(x => x > 0).TakeWhile(x => x > 0).ToList();
// Second example
series.Where(x => x > 0).Take(4).ToList();
当我设置断点并调试这两个语句时,我可以看到一个区别。
TakeWhile()
方法在满足条件的情况下执行 Where
语句。但是,Take
方法不是这种情况。第一条语句:
![enter image description here](https://istack.dev59.com/pggPa.webp)
![enter image description here](https://istack.dev59.com/tIxo6.webp)
第二条语句:
![enter image description here](https://istack.dev59.com/sJCIn.webp)
![enter image description here](https://istack.dev59.com/2Xp3J.webp)
你能解释一下为什么吗?
MulticastDelegate
吗?我不记得曾经看到过这个。我不确定你所说的“CLR将语句中的所有方法添加到此委托”是什么意思。听起来你应该用示例代码更详细地提出一个新问题。 - Jon SkeetWhere
方法,另一个用于TakeWhile
方法。据我所知,C# 编译器会在编译时使用匿名方法构造一个新的方法。CLR 将使用此方法实例化一个MulticastDelegate
实例,并将其作为谓词传递给方法。对于序列中的每个项,CLR 只需执行由此委托引用的所有方法即可。 我说得对吗? - Farhad JabiyevFunc<string, bool>
实例或其他类型。MulticastDelegate
是一个抽象类。你所说的“所有方法”并不清楚 - 这里只有一个方法。但是,你的问题与LINQ无关,如果这些细节还不够,请像我之前提到的那样提出一个新问题。 - Jon SkeetFunc<Foo,Bar>
的实例是MulticastDelegate
的实例,但是在创建实例时我不会使用该术语-我会谈论正在创建的具体实际类型。(例如,我不会说“CLR创建了System.Object实例”-出于同样的原因,这也是正确的。) - Jon Skeet