Find() 与Where().FirstOrDefault()

发布于 2025-01-06 12:41:27 字数 787 浏览 4 评论 0原文

我经常看到人们使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

时光匆匆的小流年 2025-01-13 12:41:27

IEnumerable 上的 Find 方法在哪里? (反问句。)

WhereFirstOrDefault 方法适用于多种序列,包括 ListT[ ]Collection 等。任何实现 IEnumerable 的序列都可以使用这些方法。 Find 仅适用于List。通常更适用的方法更容易重用,并且产生更大的影响。

我想我的下一个问题是他们为什么要添加这个发现。这是一个很好的提示。我唯一能想到的是 FirstOrDefault 可以返回除 null 之外的不同默认值。否则它看起来就像是毫无意义的添加

List 上毫无意义地添加 Find 早于其他方法。 List 在 .NET 2.0 中随泛型一起添加,而 Find 是该类 API 的一部分。 WhereFirstOrDefault 添加为 Linq(更高版本的 .NET 版本)的 IEnumerable 的扩展方法。我不能肯定地说,如果 Linq 与 2.0 版本一起存在,那么 Find 永远不会被添加,但对于早期 .NET 版本中出现的许多其他功能来说,情况确实如此,这些功能已过时或过时了。以后的版本是多余的。

Where is the Find method on IEnumerable<T>? (Rhetorical question.)

The Where and FirstOrDefault methods are applicable against multiple kinds of sequences, including List<T>, T[], Collection<T>, etc. Any sequence that implements IEnumerable<T> can use these methods. Find is available only for the List<T>. Methods that are generally more applicable, are then more reusable and have a greater impact.

I guess my next question would be why did they add the find at all. That is a good tip. The only thing I can think of is that the FirstOrDefault could return a different default value other than null. Otherwise it just seems like a pointless addition

Find on List<T> predates the other methods. List<T> was added with generics in .NET 2.0, and Find was part of the API for that class. Where and FirstOrDefault were added as extension methods for IEnumerable<T> with Linq, which is a later .NET version. I cannot say with certainty that if Linq existed with the 2.0 release that Find 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.

顾铮苏瑾 2025-01-13 12:41:27

我今天刚刚发现,对 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 a Where with FirstOrDefault().
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

夜清冷一曲。 2025-01-13 12:41:27

如果数据源是实体框架,则有一个非常重要的区别: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, but Where will not. This is by design.

日久见人心 2025-01-13 12:41:27

Find 仅在 实现 List,而 Where().FirstOrDefault() 适用于所有 IEnumerable

Find is only implemented in List<T>, while Where().FirstOrDefault() works with all IEnumerable<T>.

生来就爱笑 2025-01-13 12:41:27

对于 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) and items.Find(item => item.Id == id), since both enumerate over all items until a match is found. There can be performance differences when items.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 the DBContext 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.

煮酒 2025-01-13 12:41:27

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

另外,我鼓励您阅读此线程的链接问题,以了解有关在特定场景中使用 .Find() 的更好性能的更多信息 Find() 与 FirstOrDefault() 的性能

Find() is the IEnumerable equivalent of a FirstOrDefault(). 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 the FirstOrDefault() 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()

独闯女儿国 2025-01-13 12:41:27

除了安东尼的回答
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 访问 Find 需要给出结果,但如果您使用 Where().FirstOrDefault() 我们将访问所有记录然后我们得到结果。

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

in addition to Anthony answer
Where() visit through all records and then return result(s) while Find() dont need to traverse through all records if predicate match with given predicate.

so say you have List of Test class having id and name properties.

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

Will give output of 2, and only 2 visits Find needed to give result , but if you use Where().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 then Where().FirstOrDefault();

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文