フィールドの初期化とコンストラクタ

小ネタです。

namespace AssemblySize
{
    class Program
    {
        // フィールドの初期化が沢山
        private int _0 = 0;
        private int _1 = 1;
        private int _2 = 2;
        private int _3 = 3;
        private int _4 = 4;
        private int _5 = 5;
        private int _6 = 6;
        private int _7 = 7;
        private int _8 = 8;
        private int _9 = 9;

        // 最終的に1つのコンストラクタが呼ばれる
        public Program() : this(0) {}
        public Program(int a) : this(0,0) {}
        public Program(int a, int b) : this(0,0,0) {}
        public Program(int a, int b, int c) : this(0,0,0,0) {}
        public Program(int a, int b, int c, int d) : this(0,0,0,0,0) {}
        public Program(int a, int b, int c, int d, int e) {}

        static void Main(string[] args)
        {
            var program = new Program();
        }
    }
}

/*
ビルド後のアセンブリのサイズ:5120byte
*/

上記のコードをビルドするとアセンブリは5120byteでした。一方、

namespace AssemblySize
{
    class Program
    {
        // フィールドの初期化が沢山
        private int _0 = 0;
        private int _1 = 1;
        private int _2 = 2;
        private int _3 = 3;
        private int _4 = 4;
        private int _5 = 5;
        private int _6 = 6;
        private int _7 = 7;
        private int _8 = 8;
        private int _9 = 9;

        // コンストラクタはそれぞれ独立
        public Program() {}
        public Program(int a) {}
        public Program(int a, int b) {}
        public Program(int a, int b, int c)  {}
        public Program(int a, int b, int c, int d) {}
        public Program(int a, int b, int c, int d, int e) {}

        static void Main(string[] args)
        {
            var program = new Program();
        }
    }
}

/*
ビルド後のアセンブリのサイズ:5632byte
*/

こちらは、5632byteと若干大きくなっています。

両方ともフィールドに対し値を直接初期化していますが、このコードは当然のごとく、コンストラクタに展開されます。最初の例では、コンストラクタをthisでつないで最終的に1つのコンストラクタが呼ばれることになるので、ここにコードが展開されますが、2つ目の例はコンストラクタが独立しているため、それぞれにコードが展開され、サイズが膨らんでいます。

良く考えてみれば当たり前の話ですが、ソースコードだけ見ていると、ついつい忘れがちになりますよね。(^^;