LINQ, Where() vs FindAll()
Can someone explain how the开发者_Python百科 LINQ functions Where(..) and FindAll(..) differ? They both seem to do the same thing...
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
.
The biggest difference to me is that .FindAll is also available in .Net 2.0. I don't always have the luxury to program in .Net 3.5, so I try to remember the 'native' methods of the .Net generic collections.
It happened several times that I implemented an already available List method myself because I couldn't LINQ it.
What I find handy in this case is that, using VS2008, I can use type inference and the lambda syntax. These are compiler features, not framework features. This means I can write this and still remain within .Net 2.0:
var myOddNums = myNums.FindAll(n => n%2==1);
But if you do have LINQ available, keeping the difference between deferred execution and immediate execution is important.
If I recall correctly, the main difference (besides what they're implemented on: IEnumerable<T>
vs. List<T>
) is that Where
implements deferred execution, where it doesn't actually do the lookup until you need it -- using it in a foreach loop for example. FindAll
is an immediate execution method.
I did 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, other times it was faster.
Performance wise FindAll()
is better, Here is an example below. The FindAll
takes 3millisecs while the Where
took 11millisecs.
public class SortedSearch
{
public static int[] CountNumbersUsingFindAll(int[] sortedArray, int lessThan)
{
var smaller = Array.FindAll(sortedArray,x => x < lessThan);
return smaller;
}
public static IEnumerable<int> CountNumbersUsingWhere(int[] sortedArray,int lessThan)
{
var smaller = sortedArray.Where(x => x < lessThan);
return smaller;
}
}
class Program
{
static void Main(string[] args)
{
Stopwatch s = Stopwatch.StartNew();
Console.WriteLine(SortedSearch.CountNumbersUsingFindAll(new int[]{1,3,5,7},4));
Console.WriteLine(s.ElapsedMilliseconds);
s.Stop();
s.Restart();
Console.WriteLine(SortedSearch.CountNumbersUsingWhere(new int[] { 1, 3, 5, 7 }, 4));
Console.WriteLine(s.ElapsedMilliseconds);
s.Stop();
Console.ReadKey();
}
}
精彩评论