为什么使用Func <>比在泛型序列创建器上使用new()约束要快得多

Mat*_*son 13 c# optimization

考虑以下代码......

在我对Windows 7 x64 PC(Intel i7 3GHz)上的RELEASE(不是调试!)x86版本的测试中,我获得了以下结果:

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
Run Code Online (Sandbox Code Playgroud)

似乎使用Func <>来定义委托以创建新对象比直接调用"new T()"快6倍.

我觉得这有点出乎意料......我想这是因为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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*son 14

new()限制只保证传递的类型有一个参数的构造函数.如果您实际调用new T()(或者您的类型参数的名称是什么),它实际上是这样做的:

Activator.CreateInstance<T>();
Run Code Online (Sandbox Code Playgroud)

其核心是反射.