ごまなつ Blog

楽しく働ける世界を目指して

【C#】BinaryFormatterを用いた配列のコピーはかなり遅い

結論

配列をディープコピーしたいのであれば、一つずつコピーした方が良いです。

経緯

C#では、クラスの配列をArray.Copyしたときシャローコピーになります。正確に言うと、2階層目からシャローコピーになります。1次元の配列であれば、Array.Copyでディープコピーになりますが、リストのリストといった2階層目があると2階層目からシャローコピーになります。リストのリストをディープコピーしたかったので、このような方法を用いました。

public static T DeepCopyT<T>(T target)
        {
            T result;
            BinaryFormatter b = new BinaryFormatter();
            MemoryStream mem = new MemoryStream();

            try
            {
                b.Serialize(mem, target);
                mem.Position = 0;
                result = (T)b.Deserialize(mem);
            }
            finally
            {
                mem.Dispose();
            }

            return result;
        }

BinaryFormatterでMemoryStreamをシリアライズ・デシリアライズすることで、コピーしたものを返しています。 今回私がこのメソッドに渡していた配列は、class[1000]でした。クラスはa[23].b[20].c[8]個の構造でした。これを上記のメソッドに丸ごとクラスの配列を渡すと、 何と2分かかりました。さすがに実用に耐えないということで、対策を調べるとBinaryFormatterの配列のシリアライズ・デシリアライズは遅いということが分かりました。よって

for(int i=0;i<class.Length;i++)
{
          copyArray[i] = DeepCopy.DeepCopyT(class[i]);
}

として一つずつ渡すようにすると20秒で終わりました。