By KingOfHypocrites


2012-02-17 20:35:28 8 Comments

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

6 comments

@Whiplash 2019-11-05 14:44:25

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

@M Muneeb Ijaz 2018-12-06 06:10:05

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().FirtorDefault();

@Silvermind 2019-07-17 13:40:10

but if you use Where().FirstOrDefault() we will be visiting all records and then we get results. Nope. FirstOrDefault will 'bubble-up' the chain and stop enumerating everything. I use the term 'bubble-up' for lack of a better expression, because actually every selector/predicate will be passed on to the next, so the last method in the chain is actually doing work first.

@Chalky 2017-04-18 00:20:02

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.

@digiben 2012-11-02 01:02:07

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 all. Sometimes it was the same time, otherwise it was faster.

@MVCKarl 2012-11-26 11:08:36

Did you try it with Where AND FirstOrDefault? If you did perhaps try it with just only FirstOrDefault and see if Find() is still better.

@Arman McHitarian 2012-12-25 17:36:02

@MVCKarl pls see here. Find is really faster almost twice. But I can't figure out is this due to no Enumerator overhead only?

@Andrew Morton 2015-12-15 09:18:51

That sounds like you did not materialise the result with a .ToList() or .ToArray() to actually perform the query.

@percebus 2016-02-09 19:56:21

It is because Find makes use of the primary keys (hence indexes), whereas Where is a plain sql query

@C.List 2017-10-23 18:27:19

As of EF6, Find and FirstOrDefault both generate exactly the same SQL statements. You can see the SQL in a console app by doing context.Database.Log = Console.Write; The sited example is using in-memory "Find" against a list of strings, not going against a DB with primary keys. Perhaps the statement translation of the Find clause - which omits the need to do lambda expression parsing is the reason for the performance improvement in this case. Against a database I doubt you'll notice a difference in RL situations... I also wonder if it was tested using Find first instead of second...

@Gaurav 2018-04-19 10:56:48

Well, this performance improvement is because find() check in cache for object before hitting DB whereas where() always to go DB to get object

@Suncat2000 2018-10-09 11:44:59

This pertains to LINQ-to-Entities, rather than LINQ-to-objects as specified by the original poster.

@Anthony Pegram 2012-02-17 20:37:32

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.

@KingOfHypocrites 2012-02-17 21:02:24

Excellent answer. Thank you.

@Robson Rocha 2012-07-06 23:45:16

Just to complement: There is no need to call Where and First or FirstOrDefault: either First or FirstOrDefault allows you to specify a search predicate, making the Where call unnecessary

@Suncat2000 2018-10-09 11:41:24

But Where(condition).FirstOrDefault() optimizes at least as well and sometimes better than FirstOrDefault(condition) alone. We always use Where() to get the improved performance when available.

@Konstantin Salavatov 2019-08-29 16:27:55

@Suncat2000 provide an example please

@penartur 2012-02-17 20:39:24

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

@Konstantin Salavatov 2019-08-29 16:36:29

Related Questions

Sponsored Content

13 Answered Questions

[SOLVED] When to use .First and when to use .FirstOrDefault with LINQ?

  • 2009-06-21 19:15:29
  • Metro Smurf
  • 540482 View
  • 798 Score
  • 13 Answer
  • Tags:   c# .net linq

14 Answered Questions

[SOLVED] LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria

  • 2009-11-16 23:59:33
  • p.campbell
  • 273798 View
  • 489 Score
  • 14 Answer
  • Tags:   .net linq linq-to-sql

9 Answered Questions

[SOLVED] Join/Where with LINQ and Lambda

  • 2010-05-04 17:53:38
  • David
  • 819042 View
  • 421 Score
  • 9 Answer
  • Tags:   c# linq join lambda

3 Answered Questions

[SOLVED] Error: *.csproj could not import "$(MSBuildBinPath)\Microsoft.CSharp.targets" on MonoDevelop

  • 2015-02-22 00:02:46
  • Zagorodniy Olexiy
  • 8339 View
  • 12 Score
  • 3 Answer
  • Tags:   c# monodevelop

2 Answered Questions

[SOLVED] How to pass a sql connections string value to a C# program

  • 2012-05-17 20:29:49
  • John
  • 2469 View
  • 1 Score
  • 2 Answer
  • Tags:   c#

Sponsored Content