13

次のコードを検討してください...

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

Func <>を使用してデリゲートを定義し、新しいオブジェクトを作成する方が、「newT()」を直接呼び出すよりも6倍以上高速であるようです。

これは少し意外なことだと思います...ジッターによるインライン化のせいだと思いますが、「新しい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();
            }
        }
    }
}
4

1 に答える 1

14

制約はnew()、渡された型にパラメーターのないコンストラクターがあることを保証するだけです。実際に呼び出すとnew T()(またはtype引数の名前が何であれ)、実際には次のようになります。

Activator.CreateInstance<T>();

これは、基本的に反射を使用します。

于 2012-04-16T12:34:14.750 に答える