Говоря о производительности, недостаточно просто «говорить», нужно измерять вещи. Так что давайте просто сделаем это.
Я сделал довольно простой тест цикла с использованием различных конструкций и поиска суммы всех чисел внутри. Обратите внимание, что «дополнительная работа» (поиск суммы сбора) не влияет на показатель, поскольку в каждом тесте выполняется одно и то же.
[SimpleJob(RuntimeMoniker.CoreRt31)] // .net core 3.1
public class StackOverflowPerformance
{
private const int Size = 1_000_000; // 8MB cache, 1 mil ints * 4 byte each = 4MB
// hopefully this will fit into the processor cache
private List<int> _sut = new List<int>(Size); // assuming you work with List
[GlobalSetup]
public void Setup()
{
// achieve worst case scenario for our OrderBy
for (int i = Size; i > 0; --i)
{
_sut.Add(i);
}
}
[Benchmark]
public int ForeachToArray()
{
var result = 0;
foreach(var value in _sut.OrderBy(x => x).ToArray()) // change the underlying structure type
{
result += value;
}
return result;
}
[Benchmark]
public int ForeachToList()
{
var result = 0;
foreach (var value in _sut.OrderBy(x => x).ToList()) // preserve the underlying structure type
{
result += value;
}
return result;
}
[Benchmark]
public int Foreach()
{
var result = 0;
foreach (var value in _sut.OrderBy(x => x)) // OrderBy returns IEnumerable<int> this will
// most likely introduce virtual calls
{
result += value;
}
return result;
}
[Benchmark(Baseline = true)]
public int For()
{
var result = 0;
_sut = _sut.OrderBy(x => x).ToList(); // preserve the underlying type of the structure
for (int i = 0; i < _sut.Count; i++)
{
result += _sut[i];
}
return result;
}
}
И вот результаты :
Поэтому я предлагаю следующее:
Если вы беспокоитесь о производительности, вам следует подумать о преобразовании этого foreach l oop в для l oop всякий раз, когда это возможно, и имейте в виду, что это не серебряная пуля, иногда работа с IEnumerable даст лучшие результаты, чем приведение к массиву или списку.
Действительно хороший глубокий анализ производительности l oop в C#
Следующая вещь, как говорили другие, не звонить ToArray()
или ToList()
если вам не нужно использовать конкретный тип для чего-то связанного с ним, например, вы можете вызывать Find
только для List<T>
, потому что это приведет к дополнительным накладным расходам, таким как повторение цикла по l oop еще раз.