首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >查找对象实例的大小(以字节为单位),单位为c#

查找对象实例的大小(以字节为单位),单位为c#
EN

Stack Overflow用户
提问于 2009-07-14 22:02:42
回答 13查看 112.8K关注 0票数 126

对于任意实例(不同对象、组合、单个对象等的集合)

如何确定它的字节大小?

(我目前有一个各种对象的集合,我正在尝试确定它的聚合大小)

编辑:有没有人为对象写了一个扩展方法来做这件事?这将是相当整洁的国际海事组织。

EN

回答 13

Stack Overflow用户

发布于 2009-07-14 23:36:35

首先,警告:接下来的内容严格属于丑陋的、未经记录的黑客领域。不要依赖这个工作-即使它现在对你有效,明天它可能会停止工作,有任何次要或主要的.NET更新。

你可以使用这篇文章中关于CLR内部的信息MSDN Magazine Issue 2005 May - Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects --据我所知,它仍然适用。这是如何实现的(它通过类型的TypeHandle检索内部的“基本实例大小”字段)。

代码语言:javascript
复制
object obj = new List<int>(); // whatever you want to get the size of
RuntimeTypeHandle th = obj.GetType().TypeHandle;
int size = *(*(int**)&th + 1);
Console.WriteLine(size);

这在3.532位SP1上有效。我不确定字段大小在64位上是否相同-如果不是,您可能需要调整类型和/或偏移量。

这将适用于所有“普通”类型,所有实例都具有相同的、定义良好的类型。数组和字符串肯定不是这样的,我相信StringBuilder也是如此。对于它们,您需要将所有包含的元素的大小与它们的基本实例大小相加。

票数 62
EN

Stack Overflow用户

发布于 2009-07-14 22:57:41

如果您使用的是可序列化对象,则可以通过假装使用二进制序列化程序对其进行序列化来近似大小(但将输出路由到忽略状态)。

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        A parent;
        parent = new A(1, "Mike");
        parent.AddChild("Greg");
        parent.AddChild("Peter");
        parent.AddChild("Bobby");

        System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf =
           new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        SerializationSizer ss = new SerializationSizer();
        bf.Serialize(ss, parent);
        Console.WriteLine("Size of serialized object is {0}", ss.Length);
    }
}

[Serializable()]
class A
{
    int id;
    string name;
    List<B> children;
    public A(int id, string name)
    {
        this.id = id;
        this.name = name;
        children = new List<B>();
    }

    public B AddChild(string name)
    {
        B newItem = new B(this, name);
        children.Add(newItem);
        return newItem;
    }
}

[Serializable()]
class B
{
    A parent;
    string name;
    public B(A parent, string name)
    {
        this.parent = parent;
        this.name = name;
    }
}

class SerializationSizer : System.IO.Stream
{
    private int totalSize;
    public override void Write(byte[] buffer, int offset, int count)
    {
        this.totalSize += count;
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return true; }
    }

    public override void Flush()
    {
        // Nothing to do
    }

    public override long Length
    {
        get { return totalSize; }
    }

    public override long Position
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }

    public override long Seek(long offset, System.IO.SeekOrigin origin)
    {
        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }
}
票数 19
EN

Stack Overflow用户

发布于 2015-10-27 07:57:50

对于非托管类型,也就是值类型,结构:

代码语言:javascript
复制
        Marshal.SizeOf(object);

对于托管对象,我得到的近似值是近似值。

代码语言:javascript
复制
        long start_mem = GC.GetTotalMemory(true);

        aclass[] array = new aclass[1000000];
        for (int n = 0; n < 1000000; n++)
            array[n] = new aclass();

        double used_mem_median = (GC.GetTotalMemory(false) - start_mem)/1000000D;

不要使用序列化。二进制格式化程序会添加头,因此您可以更改类并将旧的序列化文件加载到修改后的类中。

此外,它不会告诉您内存中的实际大小,也不会考虑内存对齐。

通过在类的每个属性上递归地使用BiteConverter.GetBytes(prop-value)进行编辑,您将获得以字节为单位的内容,这不会计算类或引用的权重,但更接近实际。如果大小很重要,我建议使用字节数组和非托管代理类来使用指针强制转换访问值,请注意,这将是非对齐内存,因此在旧计算机上速度会很慢,但在现代RAM上的大型数据集将会快得多,因为最小化从RAM读取的大小将比未对齐的影响更大。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1128315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档