Как насчет того, чтобы проверить, а не угадать? Стыдно видеть неверный ответ.
var ints = Enumerable.Range(0, 10000000).ToList();
var sw1 = Stopwatch.StartNew();
var findall = ints.FindAll(i => i % 2 == 0);
sw1.Stop();
var sw2 = Stopwatch.StartNew();
var where = ints.Where(i => i % 2 == 0).ToList();
sw2.Stop();
Console.WriteLine("sw1: {0}", sw1.ElapsedTicks);
Console.WriteLine("sw2: {0}", sw2.ElapsedTicks);
/*
Debug
sw1: 1149856
sw2: 1652284
Release
sw1: 532194
sw2: 1016524
*/
Edit:
Даже если я переверну вышеуказанный код с
var findall = ints.FindAll(i => i % 2 == 0);
...
var where = ints.Where(i => i % 2 == 0).ToList();
... до ...
var findall = ints.FindAll(i => i % 2 == 0).Count;
...
var where = ints.Where(i => i % 2 == 0).Count();
Я получаю эти результаты
/*
Debug
sw1: 1250409
sw2: 1267016
Release
sw1: 539536
sw2: 600361
*/
Редактировать 2,0 ...
Если вы хотите получить список подмножества текущего списка, то самый быстрый метод, если FindAll (). Причина этого проста. Метод экземпляра FindAll использует индексатор текущего списка вместо конечного автомата перечислителя. Метод расширения Where () - это внешний вызов другого класса, который использует перечислитель. Если вы переходите от каждого узла в списке к следующему узлу, вам придется вызывать метод MoveNext () под обложками. Как вы можете видеть из приведенных выше примеров, еще быстрее использовать записи индекса для создания нового списка (который указывает на исходные элементы, так что объем памяти будет минимальным), чтобы даже просто получить количество отфильтрованных элементов.
Теперь, если вы собираетесь преждевременно прервать использование Enumerator, метод Where () может быть быстрее. Конечно, если вы переместите логику раннего прерывания в предикат метода FindAll (), вы снова будете использовать индексатор вместо перечислителя.
Теперь есть другие причины для использования оператора Where () (например, другие методы linq, блоки foreach и многие другие), но вопрос был в том, быстрее ли FindAll (), чем Where (). И если вы не выполняете Where (), ответ будет положительным. (При сравнении яблок с яблоками)
Я не говорю, не используйте LINQ или метод .Where (). Они делают для кода, который намного проще для чтения. Вопрос был о производительности, а не о том, насколько легко вы можете читать и понимать код. Быстрее всего, самый быстрый способ сделать эту работу - использовать шаг блока для каждого индекса и выполнять любую логику по своему усмотрению (даже ранние выходы). Причина, по которой LINQ так хорош, заключается в том, что деревья выражений и преобразования могут быть с ними сложными. Но использование итератора из метода .Where () должно пройти через тонны кода, чтобы найти путь к машине состояний в памяти, которая просто получает следующий индекс из списка. Также следует отметить, что этот метод .FindAll () полезен только для объектов, которые его реализовали (таких как Array и List.)
Еще больше ...
for (int x = 0; x < 20; x++)
{
var ints = Enumerable.Range(0, 10000000).ToList();
var sw1 = Stopwatch.StartNew();
var findall = ints.FindAll(i => i % 2 == 0).Count;
sw1.Stop();
var sw2 = Stopwatch.StartNew();
var where = ints.AsEnumerable().Where(i => i % 2 == 0).Count();
sw2.Stop();
var sw4 = Stopwatch.StartNew();
var cntForeach = 0;
foreach (var item in ints)
if (item % 2 == 0)
cntForeach++;
sw4.Stop();
Console.WriteLine("sw1: {0}", sw1.ElapsedTicks);
Console.WriteLine("sw2: {0}", sw2.ElapsedTicks);
Console.WriteLine("sw4: {0}", sw4.ElapsedTicks);
}
/* averaged results
sw1 575446.8
sw2 605954.05
sw3 394506.4
/*