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();
}
}
}
I often see people using Where.FirstOrDefault()
to do a search and grab the first element. Why not just use Find()
? Is there an advantage to the other? I couldn't tell a difference.
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();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
IEnumerable
上的Find
方法在哪里? (反问句。)Where
和FirstOrDefault
方法适用于多种序列,包括List
、T[ ]
、Collection
等。任何实现IEnumerable
的序列都可以使用这些方法。Find
仅适用于List
。通常更适用的方法更容易重用,并且产生更大的影响。在
List
上毫无意义地添加Find
早于其他方法。List
在 .NET 2.0 中随泛型一起添加,而Find
是该类 API 的一部分。Where
和FirstOrDefault
添加为 Linq(更高版本的 .NET 版本)的IEnumerable
的扩展方法。我不能肯定地说,如果 Linq 与 2.0 版本一起存在,那么Find
永远不会被添加,但对于早期 .NET 版本中出现的许多其他功能来说,情况确实如此,这些功能已过时或过时了。以后的版本是多余的。Where is the
Find
method onIEnumerable<T>
? (Rhetorical question.)The
Where
andFirstOrDefault
methods are applicable against multiple kinds of sequences, includingList<T>
,T[]
,Collection<T>
, etc. Any sequence that implementsIEnumerable<T>
can use these methods.Find
is available only for theList<T>
. Methods that are generally more applicable, are then more reusable and have a greater impact.Find
onList<T>
predates the other methods.List<T>
was added with generics in .NET 2.0, andFind
was part of the API for that class.Where
andFirstOrDefault
were added as extension methods forIEnumerable<T>
with Linq, which is a later .NET version. I cannot say with certainty that if Linq existed with the 2.0 release thatFind
would never have been added, but that is arguably the case for many other features that came in earlier .NET versions that were made obsolete or redundant by later versions.我今天刚刚发现,对 80K 对象的列表进行一些测试,发现
Find()
比使用Where
和快 1000% FirstOrDefault()
。我不知道这一点,直到在每次调用之前和之后测试计时器。
有时是相同的时间,否则,它会更快。
请参阅此https://rules.sonarsource.com/csharp/RSPEC-6602
I just found out today, doing some tests on a list of 80K objects and found that
Find()
can be up to 1000% faster than using aWhere
withFirstOrDefault()
.I didn't know that until testing a timer before and after each call.
Sometimes it was the same time, otherwise, it was faster.
see this https://rules.sonarsource.com/csharp/RSPEC-6602
如果数据源是实体框架,则有一个非常重要的区别:
Find
将查找尚未持久化的处于“已添加”状态的实体,但Where
不会。这是设计使然。There is a very important difference if the source of the data is Entity Framework:
Find
will find entities in the 'added' state that are not yet persisted, butWhere
will not. This is by design.Find
仅在中实现 List
,而Where().FirstOrDefault()
适用于所有IEnumerable
。Find
is only implemented inList<T>
, whileWhere().FirstOrDefault()
works with allIEnumerable<T>
.对于 LINQ-2-Objects,
items.FirstOrDefault(item => item.Id == id)
和items.Find(item => item. Id == id)
,因为两者都会枚举所有项目,直到找到匹配项。items.Find(id)
可能会存在性能差异,它可以使用哈希表而不是使用迭代器来查找对象。所以我想在存在问题的地方进行性能测量。更重要的是使用 EntityFramework 时的行为差异,因为
.FirstOrDefault()
执行查询并将结果添加到更改跟踪器(默认情况下;使用.FirstOrDefault()
)。 AsTracking()/.AsNoTracking()
以及用于覆盖的DBContext
设置)。当对象已被更改跟踪器跟踪时,.FirstOrDefault()
的执行可能会失败并出现异常。.Find()
将返回内存中已由更改跟踪器跟踪的对象(即更新或添加后)。因此,当对象已经被跟踪时,这不会造成问题。For LINQ-2-Objects, there is no difference between something like
items.FirstOrDefault(item => item.Id == id)
anditems.Find(item => item.Id == id)
, since both enumerate over all items until a match is found. There can be performance differences whenitems.Find(id)
, which can use a hashtable to find an object rather than using an iterator. So I guess to make performance measurements where this is an issue.More importantly is the difference in behaviour when using EntityFramework, since
.FirstOrDefault()
executes a query and adds the result to the change tracker (by default; use.AsTracking()
/.AsNoTracking()
and the settings of theDBContext
for override). The execution of.FirstOrDefault()
might fail with an exception, when the object is already tracked by the change tracker..Find()
will return the object that is already tracked by the change tracker in memory (ie. after an update or add). So this will not cause a problem when the object is already tracked.Find()
是FirstOrDefault()
的 IEnumerable 等效项。您不应将 .Where() 与.FirstOrDefault()
链接在一起,因为.Where()
会遍历整个数组,然后会迭代该列表以查找第一个物品。通过将搜索谓词放入FirstOrDefault()
方法中,您可以节省大量时间。另外,我鼓励您阅读此线程的链接问题,以了解有关在特定场景中使用
.Find()
的更好性能的更多信息 Find() 与 FirstOrDefault() 的性能Find()
is the IEnumerable equivalent of aFirstOrDefault()
. You should not chain both .Where() with.FirstOrDefault()
because the.Where()
goes through the whole array and then will iterate through that list to find the first item. You save an incredible amount of time by putting your search predicate in theFirstOrDefault()
method.Also, I encourage you to read the linked question to this thread to know more about the better performances on using the
.Find()
in specific scenarios Performance of Find() vs. FirstOrDefault()除了安东尼的回答
Where()
访问所有记录,然后返回结果,而Find()
如果谓词与给定谓词匹配,则不需要遍历所有记录。假设您有一个具有
id
和name
属性的测试类列表。将给出
2
的输出,并且只有 2 访问 Find 需要给出结果,但如果您使用Where().FirstOrDefault()
我们将访问所有记录然后我们得到结果。因此,当您知道您只想从集合中的记录中获取第一个结果时,
Find()
会比Where().FirstOrDefault();
更合适in addition to Anthony answer
Where()
visit through all records and then return result(s) whileFind()
dont need to traverse through all records if predicate match with given predicate.so say you have List of Test class having
id
andname
properties.Will give output of
2
, and only 2 visits Find needed to give result , but if you useWhere().FirstOrDefault()
we will be visiting all records and then we get results.So , when you know you only want first result from records in collection
Find()
will be more suitable thenWhere().FirstOrDefault();