Funcの初期化の違いについて

Func(T, TResult) デリゲート (System)である変数の初期化について一般的に下記の二種類あると思います。

//初期化方法1:ラムダ式
Func<int, int> f1 = i => Square(i);

//初期化方法2:メソッドグループ
Func<int, int> f2 = Square;

//ちなみにSquareは
public static int Square(int i)
{
    return i*i;
}

デコンパイルして違いを見てみる

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int, int> f1 = i => Square(i);
            Func<int, int> f2 = Square;
        }

        public static int Square(int i)
        {
            return i*i;
        }
    }
}

このコードを対象にデコンパイルして2種類の初期化の違いを見てみます。 結果このようなコードが吐き出されました。

using System;
using System.Runtime.CompilerServices;

namespace ConsoleApplication1
{
    internal class Program
    {
        [CompilerGenerated]
        [Serializable]
        private sealed class <>c
        {
            public static readonly Program.<>c <>9 = new Program.<>c();

            public static Func<int, int> <>9__0_0;

            internal int <Main>b__0_0(int i)
            {
                return Program.Square(i);
            }
        }

        private static void Main(string[] args)
        {
            Func<int, int> arg_20_0;
            if ((arg_20_0 = Program.<>c.<>9__0_0) == null)
            {
                Program.<>c.<>9__0_0 = new Func<int, int>(Program.<>c.<>9.<Main>b__0_0);
            }
            Func<int, int> f2 = new Func<int, int>(Program.Square);
        }

        public static int Square(int i)
        {
            return i * i;
        }
    }
}

デコンパイルされたコードを見てみると

  • ラムダ式で初期化された方はコンパイラがキャッシュするように特別なコードを埋め込んでいる
  • メソッドグループで初期化された方はほぼそのまま

ということがわかります。

まとめ

以上のことから複数回同じ形のFunc<,>を使う場合はラムダ式で初期化した方がよさそうです。