在内存中为新对象保留的字节

时间:2011-11-12 13:52:34

标签: c# memory-management new-operator

AFAIK,所有类型都来自

 System.Object class.

考虑到这一点,我如何计算以下代码占用的字节数:

Employee emp = new Employee("emp_name");

 List<string> empList = new List<string>();

计算他们正在采用的字节的最佳和最合适的方法是什么?

2 个答案:

答案 0 :(得分:2)

您可以使用C#sizeof运算符,但它非常有限,因为您必须在编译时指定类型,并且它只能用于内置类型。对于Employee类,您可以将它们一起添加以确定类的大小。但是,Employee类中的所有引用类型(如String)都是在堆上单独分配的,您必须添加这些对象的大小才能获得总大小。

使用一些IL技巧,您可以使用以下方法计算值类型(struct)所需的字节数。对于引用类型,它将始终返回引用的大小(32位上的4个字节):

public int GetSizeOf(Type type) {
  // Create a new method.
  var method = new DynamicMethod(
    "GetSizeOf",
    typeof(UInt32),
    new Type[0],
    GetType(),
    false
  );

  // Call sizeof(type) and return the result.
  ILGenerator generator = method.GetILGenerator();
  generator.Emit(OpCodes.Sizeof, type);
  generator.Emit(OpCodes.Ret);

  // Invoke the method.
  var func = (Func<UInt32>) method.CreateDelegate(typeof(Func<UInt32>));
  return checked((Int32) func());
}

但是,即使使用sizeof计算字节也不完全准确。堆上的对象将有一个额外的类型句柄,就像C ++中的vtable指针一样。具体如何完成这是.NET运行时的实现细节。

答案 1 :(得分:1)

嗯,根据Vance Morrison的说法,没有正式的方法可以确定这一点。尽管如此,所有的希望都不会丢失,而且你确实有一些选择(在我的脑海中):

  • 二元序列化/反序列化(如Royi Namir所述)
  • 反射(递归地累加所有字段大小,直到完全发现对象图);或
  • 强力(创建大量对象,使用GC.GetTotalMemory()静态方法在分配之前/之后测量分配的内存,并除以数组大小)

不幸的是,所有这些解决方案都只能近似分配大小,直到(如果有的话)微软正式添加这样的功能。