2010-06-16 44 views
17

有没有方法可以确定.NET中复杂对象的总大小?该对象由其他对象组成,并可能持有对其他复杂对象的引用。这个对象封装的一些对象可能是POD,其他的可能不是。确定.NET中复杂对象大小的方法?

+1

对象是否可序列化? – 2010-06-16 21:12:18

+0

他们可能会:)对不起,因为模糊,但我试图使这个问题尽可能通用。 – Polaris878 2010-06-16 21:13:55

+0

什么是C#/ .NET上下文中的“POD”?这是一个C++术语... – 2010-06-16 21:18:37

回答

10

你有什么不是一个“复杂的对象”,它是一个对象图。要确定它的总大小,你需要走这个图 - 从一些根对象开始,并使用反射枚举引用类型的字段并检索它们的值(当然还有检查循环)。

为了得到图中的一个特定对象的大小,请参阅this answer to a related question,但请注意,这是一个邪恶的黑客,完全不支持,可能会破坏(并且可能已经被打破),并可能导致批发小猫种族灭绝天上的球体。也就是说,没有“非黑客”的方式来获得准确的价值,因为它是按定义的实现细节 - 你不应该有任何用处。为了在调试/分析过程中找出应用程序的内存使用情况,黑客已经足够好了。

+0

谢谢帕维尔。当我问这个问题时,我明白了复杂性,我只是好奇是否有人已经创建了一个计算此:)的对象图遍历 – Polaris878 2010-06-16 21:50:03

1

System.Runtime.InteropServices.Marshal.SizeOf()一枪。

+0

'Marshal.SizeOf()'不能考虑子对象的大小。 – drharris 2010-06-16 21:12:28

+0

请记住它是一个安全关键功能,所以不幸在很多情况下都不起作用。 – 2010-06-16 21:12:37

+1

它给出了对象的编组表示的大小,这不是完全相同的东西。 – 2010-06-16 21:39:04

2

Tricky ...

如果两个对象指向同一个字符串变量,该怎么办?哪一个“拥有”字符串?这听起来你需要模拟一个垃圾回收来获得真正的答案。不完全重量轻。

+0

字符串在这里不是一个好例子,因为它是不可变的。 – 2010-06-16 21:24:19

+2

@保罗:不变性与此有什么关系?重点是一个对象可以持有对从外部给予它的字符串的引用(例如文件名)。该字符串是否属于该对象?它应该作为其规模的一部分吗? – 2010-06-16 21:38:37

4

简单地说,没有办法知道。假设所有对象都是可序列化的,您可以使用BinaryFormatter将它们序列化成二进制blob,然后读取它的大小。但是,这将包括一些元数据,并夸大实际的对象大小(但这将是一个合理的估计)。

对于值类型,您可以使用Marshal.SizeOf(),只有它没有考虑到任何子对象。它会计算任何内部引用类型作为指向它的指针的大小。

反思是另一种方式,但不会暴露任何私人成员占用记忆。所以,除非我错了,否则没有办法真正做到这一点。

1

以前在别处回答StackOverflow上:

Find size of object instance in bytes in c#

您需要引入不安全的代码(由于其所需的指针操作) - 该代码如下所示:

static unsafe int CalcSize(object obj) 
{ 
    RuntimeTypeHandle th = obj.GetType().TypeHandle; 
    int size = *(*(int**)&th + 1); 
    return size; 
} 

还记得将项目设置(Project-> Build选项卡)标记为“允许不安全的代码”。