Когда у вас есть некоторые методы перечисления в некоторых ваших типах (т.е. пользовательская коллекция), лучше ли использовать синтаксис LINQ или просто старое школьное перечисление (для/foreach)?
Использование .NET 3.5 является данным.
Я прошу об этом для максимальной производительности и удобочитаемости. Приложение также должно быть параллельным.
Какой из них вы предпочитаете?
Запросы Linq можно легко распараллелить, используя PLinq (встроенный в .net 4)
Я лично считаю, что Linq легче читать, но зависит от вас как разработчика.
foreach (var item in collection)
{
if (item.Value == SomeOtherValue)
performSomeProcessing();
}
против
foreach(var item in collection.Where(a => a.Value == SomeOtherValue))
{
performSomeProcessing();
}
Я думаю (хотя я лично не сравнивал это), что компилятор оптимизирует небольшие вызовы функций, поэтому производительность не должна отличаться.
Если вам абсолютно необходимо выкрутить каждую последнюю производительность, то цикл for
/foreach
сложно выполнить для эффективности. Однако, если вы собираетесь использовать parallelism и читаемость, методы расширения Enumerable<T>
и LINQ выигрывают в моей книге.
Это зависит - есть ли у вашей итерации побочные эффекты? Если это так, я бы избегал использовать любую форму LINQ, иначе используйте LINQ и PLINQ для нее простой декларативный характер.
Функция LINQ to Objects - это смешанная вещь. Поскольку это связано с множеством косвенных вызовов (каждая лямбда одна), она медленнее, иногда (когда лямбда захватывает и использует переменные из ее внешней области) 3-4 раза. И нет, компилятор (ни С#, ни JIT) не будет оптимизировать его - он не может встроить вызовы виртуальных методов и что вызов через делегат эффективно. Поэтому, если вы строго хотите производительность, foreach
будет в любом случае немного значительно быстрее.
PLINQ может облегчить разницу, но обратите внимание, что штраф достаточно значителен, чтобы вам понадобилось 4 ядра, чтобы соответствовать ему. С другой стороны, он будет увеличиваться по мере увеличения количества ядер, а простой foreach
не будет.
Я почти всегда предпочитаю использовать LINQ над стандартными циклами в моих коллекциях, но аспект параллелизации немного меняет ситуацию.
Если вы планируете использовать .NET 4.0, параллельные конструкции (в частности, Parallel.For) будут выбивать PLINQ с точки зрения распараллеливания, если вы знаете счет заранее. Разделители в PLINQ выполняют хорошую работу, но сделаны очень общей целью и не могут соответствовать стратегиям разделения, доступным, если счет известен заранее. Это будет иметь тенденцию делать Parallel.For превосходит PLINQ, когда он доступен для использования.