请考虑以下声明:
var matches = person.Contacts.Where(c => c.ContactType == searchContact.ContactType).ToList();
这将筛选具有匹配的联系人类型的所有记录 搜索联系人 对象,并仅返回已筛选的人员联系人。但是如果没有在 Where 子句末尾调用 ToList() 方法,它将返回人员的所有联系人。
现在,请考虑以下代码段。
Dictionary<int, string> colors = new Dictionary<int, string>(){ {1, "red"}, {2, "blue"}, {3, "green"}, {4, "yellow"}, {5, "red"}, {6, "blue"}, {7, "red"} };
var colorSet = colors.Where(c => c.Value == "red");
此查询将仅过滤值为"red"的元素,即使不调用 ToList() 方法也是如此。
我的问题是为什么这两个语句(一个比较值,一个比较属性)在没有 ToList() 方法调用的情况下以不同的方式运行?为什么 FirstOrDefault 而不是 Where 子句不会出现此问题?
如果有人可以解释这种情况或发布一些我可以遵循的参考资料,我真的很感激。谢谢!!
你错了。如果不调用ToList()
或其他方法来强制立即执行,这两个语句都将返回一个IQueryable<T>
。在使用foreach
循环访问查询变量之前,查询变量将保持不变。
这篇关于 MSDN 的文章应该很好地解释事情:查询执行。
您遇到的称为延迟查询执行。
在返回一系列值的查询中,查询变量 本身从不保存查询结果,只存储查询 命令。查询的执行将延迟到查询变量 在 foreach 或 For Each 循环中迭代。这被称为 延迟执行。
使用ToList()
时,发生的情况称为"立即查询执行"。
与延迟执行查询相反,查询的延迟执行会产生 值序列,执行返回单一实例值的查询 马上。单一实例查询的一些示例包括平均值、计数、 首先,马克斯。这些立即执行,因为查询必须 生成一个序列来计算单例结果。你也可以 强制立即执行。当您想要缓存 查询的结果。强制立即执行执行 不生成单例值,可以调用 ToList 方法, ToDictionary 方法,或查询或查询上的 ToArray 方法 变量。
这些是 LINQ 的核心行为。
但是如果没有在 Where 子句末尾调用 ToList() 方法,它将返回人员的所有联系人。
否,如果没有ToList
它将返回一个查询,该查询在迭代时将生成与您指定要筛选的值匹配的所有联系人。 调用ToList
只会将该查询具体化为该查询的结果。 等待一段时间并稍后迭代它,可能使用其他一些迭代方法,例如 foreach
,只有在基础数据源(在本例中为数据库)更改其数据时才会更改结果。
至于您的字典过滤器,同样适用。 在不调用ToList
的情况下,变量表示一个查询,以便在询问时获取数据,而不是该查询的结果,这是通过调用ToList
获得的结果。
属性与字段的使用在这里无关紧要。 话虽如此,这两个查询都使用属性,而不是字段。 即使一个人确实使用了一个字段,它也不会改变任何事情。
但是如果没有在 Where 子句末尾调用 ToList() 方法,它将返回人员的所有联系人。
你错了。ToList
只是强制迭代,并为您提供过滤后的元素作为List
。LINQ
使用延迟执行,这意味着直到您使用foreach
循环循环访问项目或使用ToList
或ToArray
方法,它才会执行。因此,ToList
不会更改您的项目。 Value
也是一个属性(请参阅类KeyValuePair<T,K>
),因此您正在根据两个查询中的属性值执行比较。完全没有区别。