C# 理解LINQ中的执行
我有以下产品清单C# 理解LINQ中的执行,c#,linq,C#,Linq,我有以下产品清单 List<Product> products = new List<Product> { new Product { ProductID = 1, ProductName = "first candy", UnitPrice = (decimal)10.0 }, ne
List<Product> products = new List<Product> {
new Product {
ProductID = 1,
ProductName = "first candy",
UnitPrice = (decimal)10.0 },
new Product {
ProductID = 2,
ProductName = "second candy",
UnitPrice = (decimal)35.0 },
new Product {
ProductID = 3,
ProductName = "first vegetable",
UnitPrice = (decimal)6.0 },
new Product {
ProductID = 4,
ProductName = "second vegetable",
UnitPrice = (decimal)15.0 },
new Product {
ProductID = 5,
ProductName = "third product",
UnitPrice = (decimal)55.0 }
};
var veges1 = products.Get(IsVege); //Get is a Extension method and IsVege is a Predicate
//Predicate
public static bool IsVege(Product p)
{
return p.ProductName.Contains("vegetable");
}
//Extension Method
public static IEnumerable<T> Get<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
foreach (T item in source)
{
if (predicate(item))
yield return item;
}
}
但在调试时的结果视图中,我看到了veges1的输出
如果我点击下面的代码
veges1.Count() // Breakpoint in Predicate and GET is hit and i got the count value.
这是怎么回事?你能理解一下吗
PS:我知道这方面有很多例子和问题。我试图理解这个例子,因为它会让我更容易得到东西
更新问题
我在上面做的同一个示例正在尝试对Lamda表达式做同样的操作
var veges4 = products.Get(p => p.ProductName.Contains("vegetable"));
我得到了预期的结果
其中GET是我的扩展方法,但当执行该行时,从未调用GET方法上的断点
谢谢LINQ和迭代器使用延迟执行。简而言之,yield
等待直到需要该值,然后继续执行
veges1
包含查询,而不是结果。只有在对需要执行查询的查询执行操作时,才会完成工作。例如,要为您提供veges1
的Count
,Get
需要完全执行。另一个例子是,如果执行veges1.First
,则只需要执行Get
循环的第一次迭代
强制执行查询的常用方法是使用ToList
:
// veges1 will now contain a List<Product> instead of an IEnumerable<Product>
var veges1 = products.Get(IsVege).ToList();
//veges1现在将包含一个列表而不是IEnumerable
var veges1=products.Get(IsVege.ToList();
使用退货项目时代码>返回枚举数,因此应执行以下操作:
foreach (var item in products.Get(IsVege))
{...}
或者使用.ToList()
扩展方法,该方法将为您执行foreach循环并返回项目列表。
但通过编写以下代码:
var item = products.Get(IsVege);
您刚刚收到用于遍历所需集合的正确枚举数
有关如何调试yield return
代码的详细信息,请参见此:
public void Consumer()
{
foreach(整数()中的整数i)
{
Console.WriteLine(i.ToString());
}
}
公共IEnumerable整数()
{
收益率1;
收益率2;
收益率4;
收益率8;
收益率16;
收益率16777216;
}
当你打电话时
var veges1 = products.Get(IsVege);
您只需指定一个匿名方法,它将在第一次迭代时执行。IEnumerable是一个延迟执行的接口,这意味着在您进行第一次迭代时,它的内容将被填充。它只是描述您的行为,而不是实现它。您可以将代码更改为
var veges1 = products.Get(IsVege).ToList();
这将导致方法的执行,因为ToList()将导致迭代的实现
IEnumerable在方法之外构建更大的数据集时很好,有时可以避免迭代。可能很傻。.Count函数如何知道调用哪个扩展方法并传递谓词?延迟执行。。好啊我的疑问是如何在var veges1=products.get(IsVege)的结果视图中获得o/p;线executed@user2067567:Get返回由编译器创建的特殊数据类型。此数据类型包含转换为状态机的Get
代码。这允许Count和其他方法执行Get
@user2067567:UseToList
的单个步骤。我已经扩展了我的答案。@user2067567:我不明白你的补充问题。
var veges1 = products.Get(IsVege);
var veges1 = products.Get(IsVege).ToList();