Find() vs. Where().FirstOrDefault()

C#LinqLinq to-Objects

C# Problem Overview


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

C# Solutions


Solution 1 - C#

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.

Solution 2 - C#

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.

Solution 3 - C#

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.

Solution 4 - C#

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

Solution 5 - C#

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

Solution 6 - C#

Wow i just watch the EF tutorial from MicrosofToolbox today on Youtube. He did say about using Find() and FirstOrDefault(condition) in query and Find() will search for the data you had performed something on that object( add or edit or delete - but not yet saved into the database ) meanwhile FirstOrDefault will only look for what already have been saved

Solution 7 - C#

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 https://stackoverflow.com/questions/14032709/performance-of-find-vs-firstordefault

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKingOfHypocritesView Question on Stackoverflow
Solution 1 - C#Anthony PegramView Answer on Stackoverflow
Solution 2 - C#digibenView Answer on Stackoverflow
Solution 3 - C#ChalkyView Answer on Stackoverflow
Solution 4 - C#penarturView Answer on Stackoverflow
Solution 5 - C#M Muneeb IjazView Answer on Stackoverflow
Solution 6 - C#nguyen khanhView Answer on Stackoverflow
Solution 7 - C#WhiplashView Answer on Stackoverflow