Рассмотрим следующий код...
В моих тестах для сборки RELEASE (не отладки!) x86 на компьютере под управлением Windows 7 x64 (Intel i7 3GHz) я получил следующие результаты:
CreateSequence() with new() took 00:00:00.9158071
CreateSequence() with creator() took 00:00:00.1383482
CreateSequence() with new() took 00:00:00.9198317
CreateSequence() with creator() took 00:00:00.1372920
CreateSequence() with new() took 00:00:00.9340462
CreateSequence() with creator() took 00:00:00.1447375
CreateSequence() with new() took 00:00:00.9344077
CreateSequence() with creator() took 00:00:00.1365162
Кажется, что использование Func < > для определения делегата для создания новых объектов более чем в 6 раз быстрее, чем вызов "нового T()" напрямую.
Я нахожу это немного неожиданным... Я предполагаю, что это связано с некоторой инкрустацией, сделанной Jitter, но я бы подумал, что она также сможет оптимизировать "новый T()".
Есть ли у кого есть объяснение?
Возможно, я ошибаюсь. (Я рассмотрел эффект, который может иметь сборщик мусора, но переупорядочивание кода и добавление GC.Collect() и т.д. Не сильно меняют результаты).
В любом случае, здесь код:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
int repeats = 100;
int count = 100000;
for (int outer = 0; outer < 4; ++outer)
{
sw.Restart();
for (int inner = 0; inner < repeats; ++inner)
{
CreateSequence<object>(count).Count();
}
Console.WriteLine("CreateSequence() with new() took " + sw.Elapsed);
sw.Restart();
for (int inner = 0; inner < repeats; ++inner)
{
CreateSequence(count, () => new object()).Count();
}
Console.WriteLine("CreateSequence() with creator() took " + sw.Elapsed);
Console.WriteLine();
}
}
public static IEnumerable<T> CreateSequence<T>(int n) where T: new()
{
for (int i = 0; i < n; ++i)
{
yield return new T();
}
}
public static IEnumerable<T> CreateSequence<T>(int n, Func<T> creator)
{
for (int i = 0; i < n; ++i)
{
yield return creator();
}
}
}
}