LINQ, Where() vs FindAll()
FindAll()
is a function on the List<T>
type, it's not a LINQ extension method like Where
. The LINQ extension methods work on any type that implements IEnumerable
, whereas FindAll
can only be used on List<T>
instances (or instances of classes that inherit from it, of course).
Additionally, they differ in actual purpose. Where
returns an instance of IEnumerable
that is executed on-demand when the object is enumerated. FindAll
returns a new List<T>
that contains the requested elements. FindAll
is more like calling Where(...).ToList()
on an instance of IEnumerable
.
FindAll Vs Where
You can find your answer here: LINQ, Where() vs FindAll() . Basically if you call .ToList() on your "Where" they would be the same.
You can find more about the differences between deferred and immediate execution: https://code.msdn.microsoft.com/LINQ-Query-Execution-ce0d3b95
FindAll vs Where extension-method
Well, FindAll
copies the matching elements to a new list, whereas Where
just returns a lazily evaluated sequence - no copying is required.
I'd therefore expect Where
to be slightly faster than FindAll
even when the resulting sequence is fully evaluated - and of course the lazy evaluation strategy of Where
means that if you only look at (say) the first match, it won't need to check the remainder of the list. (As Matthew points out, there's work in maintaining the state machine for Where
. However, this will only have a fixed memory cost - whereas constructing a new list may require multiple array allocations etc.)
Basically, FindAll(predicate)
is closer to Where(predicate).ToList()
than to just Where(predicate)
.
Just to react a bit more to Matthew's answer, I don't think he's tested it quite thoroughly enough. His predicate happens to pick half the items. Here's a short but complete program which tests the same list but with three different predicates - one picks no items, one picks all the items, and one picks half of them. In each case I run the test fifty times to get longer timing.
I'm using Count()
to make sure that the Where
result is fully evaluated. The results show that collecting around half the results, the two are neck and neck. Collecting no results, FindAll
wins. Collecting all the results, Where
wins. I find this intriguing: all of the solutions become slower as more and more matches are found: FindAll
has more copying to do, and Where
has to return the matched values instead of just looping within the MoveNext()
implementation. However, FindAll
gets slower faster than Where
does, so loses its early lead. Very interesting.
Results:
FindAll: All: 11994
Where: All: 8176
FindAll: Half: 6887
Where: Half: 6844
FindAll: None: 3253
Where: None: 4891
(Compiled with /o+ /debug- and run from the command line, .NET 3.5.)
Code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
class Test
{
static List<int> ints = Enumerable.Range(0, 10000000).ToList();
static void Main(string[] args)
{
Benchmark("All", i => i >= 0); // Match all
Benchmark("Half", i => i % 2 == 0); // Match half
Benchmark("None", i => i < 0); // Match none
}
static void Benchmark(string name, Predicate<int> predicate)
{
// We could just use new Func<int, bool>(predicate) but that
// would create one delegate wrapping another.
Func<int, bool> func = (Func<int, bool>)
Delegate.CreateDelegate(typeof(Func<int, bool>), predicate.Target,
predicate.Method);
Benchmark("FindAll: " + name, () => ints.FindAll(predicate));
Benchmark("Where: " + name, () => ints.Where(func).Count());
}
static void Benchmark(string name, Action action)
{
GC.Collect();
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 50; i++)
{
action();
}
sw.Stop();
Console.WriteLine("{0}: {1}", name, sw.ElapsedMilliseconds);
}
}
C# FindAll VS Where Speed
The FindAll method of the List<T> class actually constructs a new list object, and adds results to it. The Where extension method for IEnumerable<T> will simply iterate over an existing list and yield an enumeration of the matching results without creating or adding anything (other than the enumerator itself.)
Given a small set, the two would likely perform comparably. However, given a larger set, Where should outperform FindAll, as the new List created to contain the results will have to dynamically grow to contain additional results. Memory usage of FindAll will also start to grow exponentially as the number of matching results increases, where as Where should have constant minimal memory usage (in and of itself...excluding whatever you do with the results.)
Linq FindAll and Where returns different results
Where
and FindAll
are equivalent, except that in terms of execution, Where
is deferred, but FindAll
is immediate.
Source: This SO thread.
Find() vs. Where().FirstOrDefault()
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.
Using List in FindAll function -C# LinQ
You can use LINQ Contains() extension method like this.
The Linq Contains Method in C# is used to check whether a sequence or collection (i.e. data source) contains a specified element or not. If the data source contains the specified element, then it returns true else return false
List<int> locations= // code to get location id's here
items = ctx.listName.Where(x=>locations.Contains(x.locationId)).ToList();
Related Topics
C# Create/Modify/Read .Xlsx Files
Cannot Access Non-Static Field
How to Create a Custom Attribute in C#
Generating Xml File Using Xsd File
How to Specify a Generic Type in Xaml (Pre .Net 4 Framework)
Implementing Audit Log/Change History with MVC & Entity Framework
Convert from SQLdatareader to JSON
C# Static Variables - Scope and Persistence
In Wpf Can You Filter a Collectionviewsource Without Code Behind
Does Distinct() Method Keep Original Ordering of Sequence Intact
Datatrigger Does Not Change Text Property
Jcontainer, Jobject, Jtoken and Linq Confusion
Multiple File-Extensions Searchpattern for System.Io.Directory.Getfiles
.Net - Windowstyle = Hidden VS. Createnowindow = True
How Expensive Is the Lock Statement