简体   繁体   English

Linq Where子句中比较两个属性和两个值之间的区别

[英]Difference between comparing two properties and two values in Linq Where clause

Please consider the following statement: 请考虑以下声明:

var matches = person.Contacts.Where(c => c.ContactType == searchContact.ContactType).ToList();

This will filter all the records with matching ContactType of searchContact object and returns only the filtered Contacts of person. 这将过滤与searchContact对象的ContactType匹配的所有记录,并仅返回已过滤人员的Contacts。 But without ToList() method call at the end of the Where clause, it will return all the Contacts of person. 但是,如果在Where子句的末尾没有调用ToList()方法,它将返回person的所有Contacts。

Now, consider the following code segment. 现在,考虑以下代码段。

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");

This query will filter only the elements with value "red", even without calling ToList() method. 该查询将仅过滤值为“ red”的元素,即使不调用ToList()方法也是如此。

My question is why this two statements (one that compares values and one that compares properties) behave in a different way without ToList() method call? 我的问题是,为什么这两个语句(一个比较值而一个比较属性)在没有ToList()方法调用的情况下以不同的方式表现呢? Why this problem does not occur with FirstOrDefault instead of Where clause? 为什么使用FirstOrDefault而不是Where子句不会发生此问题?

I really appreciate, if anyone can explain the scenario or post some references that I can follow. 我真的很感激,如果有人可以解释这种情况或发布一些我可以遵循的参考资料。 Thanks!! 谢谢!!

You are mistaken. 你误会了。 Without calling ToList() or another method to force immediate execution, both statements will return an IQueryable<T> . 在不调用ToList()或其他方法强制立即执行的情况下,两个语句都将返回IQueryable<T> Until you iterate over your query variable by using a foreach the query variable remains just that. 在使用foreach查询变量之前,查询变量将保持不变。

This article on MSDN should explain things well: Query Execution . 有关MSDN的这篇文章应该很好地解释一下: 查询执行

What you are experiencing is called Deferred Query Execution . 您遇到的情况称为延迟查询执行

In a query that returns a sequence of values, the query variable itself never holds the query results and only stores the query commands. 在返回值序列的查询中,查询变量本身从不保存查询结果,而仅存储查询命令。 Execution of the query is deferred until the query variable is iterated over in a foreach or For Each loop. 查询的执行被推迟,直到在foreach或For Each循环中迭代查询变量为止。 This is known as deferred execution. 这称为延迟执行。

When you use ToList() what occurs is known as Immediate Query Execution . 当您使用ToList() ,发生的事情称为即时查询执行

In contrast to the deferred execution of queries that produce a sequence of values, queries that return a singleton value are executed immediately. 与产生一系列值的查询的延迟执行相反,返回单值的查询将立即执行。 Some examples of singleton queries are Average, Count, First, and Max. 单例查询的一些示例是“平均值”,“计数”,“第一”和“最大值”。 These execute immediately because the query must produce a sequence to calculate the singleton result. 这些操作将立即执行,因为查询必须产生一个序列来计算单例结果。 You can also force immediate execution. 您还可以强制立即执行。 This is useful when you want to cache the results of a query. 当您要缓存查询结果时,这很有用。 To force immediate execution of a query that does not produce a singleton value, you can call the ToList method, the ToDictionary method, or the ToArray method on a query or query variable. 要强制立即执行不产生单例值的查询,可以在查询或查询变量上调用ToList方法,ToDictionary方法或ToArray方法。

These are core behaviors of LINQ. 这些是LINQ的核心行为。

But without ToList() method call at the end of the Where clause, it will return all the Contacts of person. 但是,如果在Where子句的末尾没有调用ToList()方法,它将返回person的所有Contacts。

No, without ToList it will return a query which, when iterated, will yield all of the contacts matching the value you specified to filter on. 不,没有ToList ,它将返回一个查询,该查询在进行迭代时将产生与您指定要过滤的值匹配的所有联系人。 Calling ToList only materializes that query into the results of that query. 调用ToList只会将该查询具体化为该查询的结果。 Waiting a while and iterating it later, possibly using some other method of iteration such as foreach , will only change the results if the underlying data source (in this case, a database, by the look of thigns) changes its data. 等待片刻,然后再进行迭代(可能使用其他迭代方法,例如foreach ,只有在基础数据源(在这种情况下,从外观上看,数据库)更改其数据时,才会更改结果。

As to your dictionary filter, the same thing applies. 至于字典过滤器,同样适用。 Without calling ToList the variable represents a query to get the data when asked , not the results of that query , which is what you would get by calling ToList . 在不调用ToList的情况下,变量表示一个查询,用于在询问时获取数据 ,而不是查询的结果 ,这就是通过调用ToList可以得到的结果。

The use of a property versus a field is irrelevant here. 这里,属性与字段的使用无关紧要。 Having said that , both queries are using properties, not fields. 话虽如此 ,两个查询都使用属性,而不是字段。 Even if one did use a field though, it wouldn't change a thing. 即使使用字段,也不会改变任何事情。

But without ToList() method call at the end of the Where clause, it will return all the Contacts of person. 但是,如果在Where子句的末尾没有调用ToList()方法,它将返回person的所有Contacts。

You are wrong. 你错了。 ToList is just forces the iteration and gives you your filtered elements as a List . ToList只是强制迭代,并为您提供过滤后的元素作为List LINQ uses deferred execution which means until you use foreach loop to iterate over items or use ToList or ToArray methods, it's not executed.So ToList doesn't change your items. LINQ使用延迟执行,这意味着直到您使用foreach循环来迭代项目或使用ToListToArray方法之前,它都不会执行。因此, ToList不会更改您的项目。 Value is also a property (see KeyValuePair<T,K> class), so you are performing a comparison based on property values in both query.There is no difference at all. Value也是一个属性(请参见KeyValuePair<T,K>类),因此您将基于两个查询中的属性值进行比较。根本没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM