Find()与Where().FirstOrDefault()

我经常看到人们使用Where.FirstOrDefault()来进行搜索并获取第一个元素。为什么不直接使用Find()?对方有优势吗?我看不出有什么区别。

namespace LinqFindVsWhere
{
class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
list.AddRange(new string[]
{
"item1",
"item2",
"item3",
"item4"
});


string item2 = list.Find(x => x == "item2");
Console.WriteLine(item2 == null ? "not found" : "found");
string item3 = list.Where(x => x == "item3").FirstOrDefault();
Console.WriteLine(item3 == null ? "not found" : "found");
Console.ReadKey();
}
}
}
149222 次浏览

其中是IEnumerable<T>上的Find方法?(反问句)

WhereFirstOrDefault方法适用于多种序列,包括List<T>T[]Collection<T>等。实施IEnumerable<T>的任何序列都可以使用这些方法。Find仅适用于List<T>。通常更适用的方法则更可重复使用,并具有更大的影响。

我想我的下一个问题是他们为什么要添加这个发现。这是一个很好的提示。我唯一能想到的是,FirstOrDefault可以返回不同的默认值,而不是null.否则,这似乎只是一个毫无意义的补充。

List<T>上的Find早于其他方法。List<T>是随.NET 2.0中的泛型一起添加的,而Find是该类的API的一部分。WhereFirstOrDefault是随LINQ(.NET的较新版本)一起作为IEnumerable<T>的扩展方法添加的。我不能肯定地说,如果LINQ与2.0版本一起存在,那么Find将永远不会被添加,但可以证明的是,早期.NET版本中的许多其他功能在后来的版本中被淘汰或冗余。

Find只是List<T>中的已实施,而Where().FirstOrDefault()适用于所有IEnumerable<T>

我今天刚刚发现,在对80K对象的列表进行一些测试时,发现Find()比使用WhereFirstOrDefault()最多快1000%。我不知道,直到测试计时器之前和之后的每一个。有时是同一时间,否则会更快。

如果数据源是实体框架,则有一个非常重要的区别:Find将查找处于“已添加”状态且尚未持久化的实体,但Where则不会。这是设计好的。

除了安东尼的回答 Where()访问所有记录,然后返回结果,而Find()如果谓词与给定谓词匹配,则不需要遍历所有记录。

假设您有一个测试类列表,它具有idname属性。

 List<Test> tests = new List<Test>();
tests.Add(new Test() { Id = 1, Name = "name1" });
tests.Add(new Test() { Id = 2, Name = "name2" });
tests.Add(new Test() { Id = 3, Name = "name3" });
tests.Add(new Test() { Id = 4, Name = "name2" });
var r = tests.Find(p => p.Name == "name2");
Console.WriteLine(r.Id);

将给出2的输出,并且只有2访问时才需要给出结果,但如果您使用Where().FirstOrDefault(),我们将访问所有记录,然后获得结果。

因此,当您知道您只想从集合中的记录中获得第一个结果时,Find()将比Where().FirstOrDefault();更合适

Find()FirstOrDefault()的IEnumerable等效项。您不应该将两个.where()与.FirstOrDefault()链接在一起,因为.Where()遍历整个数组,然后将遍历该列表以找到第一项。通过将搜索谓词放在FirstOrDefault()方法中,可以节省大量的时间。

此外,我鼓励您阅读此主题的链接问题,以了解更多有关在特定情况下使用.Find()find()与FirstOrDefault()的性能比较的更好性能的信息。

对于LINQ-2对象,items.FirstOrDefault(item => item.Id == id)items.Find(item => item.Id == id)之间没有区别,因为两者都会枚举所有项目,直到找到匹配项。当items.Find(id)(它可以使用哈希表而不是迭代器来查找对象)时,可能会存在性能差异。所以我想在这是一个问题的地方进行性能测量。

更重要的是使用实体框架时的行为差异,因为.FirstOrDefault()执行查询并将结果添加到更改跟踪器(默认情况下;使用.AsTracking()/.AsNoTracking()DBContext的设定进行超越)。当更改跟踪程序已跟踪.FirstOrDefault()时,该对象的执行可能会因异常而失败。

.Find()将返回内存中更改跟踪程序已跟踪的对象(即,在更新或添加之后)。因此,当对象已被跟踪时,这不会导致问题。