C# - オブジェクトのメモリサイズを取得

 クラウディア
1. 概要
2. シリアライズして調べる

1. 概要

 「C#」の場合、「C」に比べると、勝手にメモリを確保してくれるので、あまりメモリに関して意識はしないのですが・・・。  逆に意識しないため、気づくと大量にメモリを消費してしまっていることがあります。  これは、なんじゃろか・・・と。  でまぁ、オブジェクトのメモリサイズを知りたいと思ったわけです。  本ページは、下記のサイトを参考にさせていただきました。
c# — メモリ内のオブジェクトサイズを取得する方法?」
「C# でクラス名を取得する

2. シリアライズして調べる

 オブジェクトが、シリアライズ可能であれば、シリアライズして、バイト数を測るという方法があります。  すなわち

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;

public class MyMain
{
	[Serializable]
	public class myClass
	{
		public int		i	= 0;												// 数値型要素
		public string	s	= String.Empty;										// 文字列型要素
	}

	static public void Main ()
	{
		List<myClass> list = new List<myClass>
			{
				new myClass { i = 1, s = "A" },
			};


		printObjectSize(list);

		list.Add(new myClass { i = 2, s = "B" });
		printObjectSize(list);

		list.Add(new myClass { i = 3, s = "C" });
		printObjectSize(list);
	}

	static public void printObjectSize(object Object)
	{
		BinaryFormatter bf = new BinaryFormatter();
		MemoryStream ms = new MemoryStream();
		byte[] Array;
		bf.Serialize(ms, Object);
		Array = ms.ToArray();

        Console.WriteLine("["+Object.GetType().Name +"] サイズ["+ Array.Length.ToString("#,0") +"]");
	}
}
 てな、ソースを書き、ロードモジュールを作成して、実行すると、下記の結果が得られます。

[List`1][Object][Object][357]
[List`1][Object][Object][382]
[List`1][Object][Object][406]
 33~42行の「printObjectSize」の書き方次第ですね。  戻り値を何にするかとか、出力の仕方は、工夫次第かと・・・。  サイズ以外の部分は、オブジェクトに関する情報を出力しようとしましたが、うまくいきませんでした。  まぁ、「nearly equal」な値になるかと思います。  ただ、これ、巨大な「List」でやろうとしたら「System.Runtime.Serialization.SerializationException: 内部配列を Int32.MaxValue 要素を超えて展開することはできません。」てな例外になってしまいました。