LINQ扩展方法 - Any() vs. Where() vs. Exists() LINQ是一种用于.NET Framework的语言集成查询,它允许使用类似SQL的语法从各种数据源中检索和操作数据。 LINQ扩展方法是一组可用于查询集合的方法。其中三个常见的方法是Any(),Where()和Exists()。 - Any()方法用于确定集合中是否存在任何元素。如果集合为空,则返回false。 - Where()方法用于筛选集合以仅包含满足指定条件的元素。 - Exists()方法用于确定集合中是否存在与指定谓词匹配的元素。 这些方法可以帮助简化代码并提高性能。选择正确的方法取决于您要解决的问题。

66

不幸的是,这些方法的名称作为搜索词非常糟糕,我一直找不到一个好的资源来解释这些方法之间的差异--如何选择使用哪个。

谢谢。

编辑:

我试图完全理解的查询类似于这样:

context.Authors.Where(a => a.Books.Any(b => b.BookID == bookID)).ToList();

感谢所有回答过的人。


8
我建议您查看101 LINQ示例 - Kobi
类似的问题在这里:https://dev59.com/KnNA5IYBdhLWcg3wpvpg - Esteban Araya
7个回答

107

Where方法返回一个新的由满足条件的元素组成的序列。

Any方法返回一个布尔值;它有一个带有谓词的版本(在这种情况下,它返回是否存在任何匹配项),也有一个不带谓词的版本(在这种情况下,它返回查询至今是否包含任何项)。

我对Exists方法不太确定 - 它不是LINQ标准查询运算符。如果存在Entity Framework的版本,则可能基于键检查存在性 - 这是一种特殊形式的Any吗?(List<T>中有一个类似于Any(predicate)Exists方法,但它比LINQ更早。)


8
是的,正如我发布的那样,它是List<T>的一部分,而不是LINQ的一部分。 - Jon Skeet
但是在函数中,.Any.Exists 是完全相同的。 - Flater
1
@Flater:Exists 的哪个版本?List<T>.Exists - Jon Skeet

8

context.Authors.Where(a => a.Books.Any(b => b.BookID == bookID)).ToList();

a.Books 是该作者的书籍列表。只要你已经建立了外键关系,Linq-to-Sql 就会自动创建该属性。

因此,a.Books.Any(b => b.BookID == bookID) 的意思是“这位作者的任何一本书的 ID 是否为 bookID”,完整表达式的意思是“写有编号为 bookID 的书的作者是谁?”

也可以像下面这样书写:

  from a in context.Authors
  join b in context.Books on a.AuthorId equal b.AuthorID
  where b.BookID == bookID
  select a;

更新: 据我所知,Any() 只返回一个 bool。它的有效实现是:

 public Any(this IEnumerable<T> coll, Func<T, bool> predicate)
 {
     foreach(T t in coll)
     {
         if (predicte(t))
            return true;
     }
     return false;
 }

我认为困扰我的部分是Any()返回一个布尔值,这意味着我正在阅读“是的,作者在他们的收藏中确实有这个BookID的书籍。”是否有另一个返回不同结果的Any()重载函数? - asfsadf
是啊,这就是我为什么感到困惑的原因。Any()方法的链接方式对我来说毫无意义。它并不返回一本书,而是一个布尔值。天哪,我在这个问题上一无所知。也许我只需要再泡一壶咖啡。顺便说一下,非常感谢你的努力。 - asfsadf
2
我没有看到问题。Any() 返回一个布尔值,Where() 期望一个布尔值。大家都很开心! - James Curran
这个傻瓜帽让我的头发痒,有时会分散注意力。我相信我最终会掌握它的。 - asfsadf
据我所了解,Any()和Where()之间的区别在于,如果满足条件,Any返回true,而Where返回满足条件的元素。因此,使用Any来询问是否有任何书籍具有特定的ID,并使用Where来询问哪些书籍具有该ID(并将它们返回)。 - Techek

7

以下是可枚举的Linq扩展的搜索方法。这些方法都是Enumerable类的静态方法,因此有Enumerable.Any、Enumerable.Where和Enumerable.Exists。为方便下次查找,您可以搜索以下链接:

由于第三个方法没有可用结果,我认为您指的是List.Exists,因此可以使用以下链接:

我还建议您访问hookedonlinq.com,因为该网站提供了非常全面和清晰的指南,以及关于Linq方法与延迟和惰性相关行为的明确解释。


谢谢提供这些链接。我搜索了“ienumerable<>.any()”,看起来很接近,但是没有用。 - asfsadf

3

Any - 布尔函数,当列表中的任何对象满足函数参数中设置的条件时返回true。例如:

List<string> strings = LoadList();
boolean hasNonEmptyObject = strings.Any(s=>string.IsNullOrEmpty(s));

Where - 函数返回满足函数参数中设定条件的所有对象列表。例如:

IEnumerable<string> nonEmptyStrings = strings.Where(s=> !string.IsNullOrEmpty(s));

Exists - 与任何其他方法基本相同,但它不是通用的 - 它是在List类中定义的,而Any是在IEnumerable接口中定义的。


2
你的第二个例子无法编译,因为Where返回IEnumerable<T> - Jon Skeet

2

Any()函数会返回集合中是否存在任意一个元素满足谓词条件,如果有则返回true。(Any()不会遍历整个集合,它在找到第一个匹配项后就会停止遍历。)

Where()函数会返回一个枚举集合,其中包含所有满足谓词条件的元素。

Exists()函数与Any()函数做的事情相同,只是它是早期实现的版本,在LINQ出现之前就存在于List中。


5
不在 IList 上 - 只有 List<T> - Jon Skeet

1

IEnumerable引入了许多扩展方法,可以帮助您传递自己的委托并从IEnumerable返回结果。其中大部分都是Func类型。

Func接受一个参数T并返回TResult。

在Where的情况下 - Func:它接受T的IEnumerable并返回bool。where最终将返回Func返回true的T的IEnumerable。

因此,如果您有1,5,3,6,7作为IEnumerable,并编写.where(r => r<5),它将返回新的IEnumerable 1,3。

Any - Func基本上具有相似的签名,但仅当任何条件对IEnumerable返回true时才返回true。在我们的例子中,它将返回true,因为存在一些元素r<5。

Exists - 另一方面,谓词仅在任何一个谓词返回true时才返回true。因此,在我们的例子中,如果您传递.Exists(r => 5),它将返回true,因为5是IEnumerable中存在的元素。


0
foreach (var item in model.Where(x => !model2.Any(y => y.ID == x.ID)).ToList())
{
enter code here
}

你也可以使用Contains来完成同样的工作。

其次,Where会给你一个新的值列表。 第三,使用Exist不是一个好习惯,你可以通过Anycontains来实现你的目标。

EmployeeDetail _E = Db.EmployeeDetails.where(x=>x.Id==1).FirstOrDefault();

希望这能解决你的困惑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接