LINQ,Where() vs FindAll()

164
有人能解释一下 LINQ 函数 Where(..) 和 FindAll(..) 有什么区别吗?它们似乎都做同样的事情...

可能重复的问题:FindAll vs Where extension-method - Ryan Gates
5个回答

264
FindAll()List<T> 类型的一个函数,它不像 Where 那样是 LINQ 扩展方法。LINQ 扩展方法适用于任何实现了 IEnumerable 接口的类型,而 FindAll 只能用于 List<T> 实例(当然也包括继承自该类的实例)。

此外,它们在实际用途上也有所不同。 Where 返回一个 IEnumerable 实例,在枚举对象时按需执行。 FindAll 则返回一个包含请求元素的新 List<T>FindAll 更像是对一个 IEnumerable 实例调用 Where(...).ToList()


35
是的,Where是findall的懒惰版本。 - Pierreten
4
http://code.msdn.microsoft.com/LINQ-Query-Execution-ce0d3b95 解释了延迟执行和立即执行之间的区别。基本上,在某些情况下,您不需要整个列表,您可能只想循环遍历项目直到发生某些事情,然后停止。这就是延迟执行的用途,但根据实现方式,可能会导致不可预测的结果(所有内容都在链接中解释)。希望这可以帮助您。 - nurchi
重要的是要知道,感谢您的回答。我看到在使用"yield return element"时,而findall构造适当的列表并返回。 - zzfima

12

对我来说最大的区别是.FindAll也适用于.Net 2.0。我并不总是有幸编程使用 .Net 3.5,所以我尽量记住 .Net 泛型集合的“本地”方法。

已经发生过好几次,因为无法使用LINQ,我自己实现了一个已有的List方法。

在这种情况下,我觉得很方便的是,使用VS2008,我可以使用类型推断和lambda语法。这些是编译器功能,而不是框架功能。这意味着我可以编写以下代码,并仍然保持在 .Net 2.0 中:

var myOddNums = myNums.FindAll(n => n%2==1);

但如果您确实有LINQ,那么保持延迟执行和立即执行之间的区别是很重要的。


8

如果我没记错的话,除了它们所实现的类型不同(IEnumerable<T> vs. List<T>)外,主要区别在于Where实现了延迟执行,在您需要时才会进行查找,例如在foreach循环中使用。而FindAll是一种立即执行方法。


4

我对一个包含80K对象的列表进行了一些测试,发现使用Find()比使用WhereFirstOrDefault()快上多达1000%。在每次调用前后测试计时器之前,我并不知道这一点。有时候时间相同,有时候更快。


6
你尝试过访问集合吗?Enumerable.Where()使用延迟执行,只有在访问集合时才会评估,这可能会导致对于其速度是否更快产生错误的观念。尽管如此,通常使用可枚举对象比使用静态集合(例如Type<T>和Array<T>)更快。 - Sebastian Job Bjørnager Jensen
3
关于FindAll的问题。显然,使用Find相较于使用Where(取所有值)并获取FirstOrDefault会更快。 - Vivek MVK
你尝试过在FindAll()中使用FirstOrDefault()吗? - shieldgenerator7
1
使用 Where 或 FindAll 与 .Count() 函数几乎具有相同的性能,但是当 FindAll 使用 Length 属性而不是 Count() 时存在巨大差异,因此 FindAll 更适合搜索和过滤数组。 - Adebayo Vicktor

-1

就性能而言,FindAll() 更好。以下是一个示例。 FindAll 花费了3毫秒,而 Where 则花费了11毫秒

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

1
你处于什么样的环境中,以至于一个运行遍历4个整数的方法需要接近3秒甚至是11秒?这些结果似乎存在多个数量级的偏差。也许是3毫秒和11毫秒之间的区别吗?如果是这种情况,我建议在计时过程中不要包括WriteLine语句。 - Mark Meuer
实际上是毫秒,而不是秒。 - Adebayo Vicktor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接