当前位置:  开发笔记 > 编程语言 > 正文

使用C#获取字段大小(以字节为单位)

如何解决《使用C#获取字段大小(以字节为单位)》经验,为你挑选了4个好方法。

我有一个类,我想检查它的字段并最终报告每个字段占用的字节数.我假设所有字段都是Int32,byte等类型.

如何轻松找出该字段占用的字节数?

我需要这样的东西:

Int32 a;
// int a_size = a.GetSizeInBytes;
// a_size should be 4

Jon Skeet.. 99

基本上你不能.它将取决于填充,这可能基于您正在使用的CLR版本和处理器等.假设它没有引用其他对象,则更容易计算出对象的总大小:创建一个大数组,使用GC.GetTotalMemory作为基点,使用对类型的新实例的引用填充数组,然后再次调用GetTotalMemory.取一个值远离另一个值,除以实例数.您可能应该事先创建一个实例,以确保没有新的JITted代码对该数字有贡献.是的,它听起来像黑客一样 - 但我之前已经用它效果很好.

就在昨天,我认为为此编写一个小助手类是个好主意.如果您有兴趣,请告诉我.

编辑:还有其他两个建议,我想解决它们.

首先,sizeof运算符:这只显示了抽象中类型占用了多少空间,没有应用填充.(它包括结构中的填充,但不是在另一种类型中应用于该类型的变量的填充.)

接下来,Marshal.SizeOf:这只显示编组后的非托管大小,而不是内存中的实际大小.正如文档明确指出:

返回的大小实际上是非托管类型的大小.对象的非托管和托管大小可以不同.对于字符类型,大小受应用于该类的CharSet值的影响.

再次,填充可以有所作为.

只是为了澄清我对填充相关的含义,请考虑以下两个类:

class FourBytes { byte a, b, c, d; }
class FiveBytes { byte a, b, c, d, e; }

在我的x86盒子上,一个FourBytes实例需要12个字节(包括开销).FiveBytes的实例需要16个字节.唯一的区别是"e"变量 - 那么需要4个字节吗?好吧,有点......而不是.显然,您可以从FiveBytes中删除任何单个变量以使大小减小到12个字节,但这并不意味着每个变量占用4个字节(考虑删除所有变量!).单个变量的成本并不是一个在这里很有意义的概念.



1> Jon Skeet..:

基本上你不能.它将取决于填充,这可能基于您正在使用的CLR版本和处理器等.假设它没有引用其他对象,则更容易计算出对象的总大小:创建一个大数组,使用GC.GetTotalMemory作为基点,使用对类型的新实例的引用填充数组,然后再次调用GetTotalMemory.取一个值远离另一个值,除以实例数.您可能应该事先创建一个实例,以确保没有新的JITted代码对该数字有贡献.是的,它听起来像黑客一样 - 但我之前已经用它效果很好.

就在昨天,我认为为此编写一个小助手类是个好主意.如果您有兴趣,请告诉我.

编辑:还有其他两个建议,我想解决它们.

首先,sizeof运算符:这只显示了抽象中类型占用了多少空间,没有应用填充.(它包括结构中的填充,但不是在另一种类型中应用于该类型的变量的填充.)

接下来,Marshal.SizeOf:这只显示编组后的非托管大小,而不是内存中的实际大小.正如文档明确指出:

返回的大小实际上是非托管类型的大小.对象的非托管和托管大小可以不同.对于字符类型,大小受应用于该类的CharSet值的影响.

再次,填充可以有所作为.

只是为了澄清我对填充相关的含义,请考虑以下两个类:

class FourBytes { byte a, b, c, d; }
class FiveBytes { byte a, b, c, d, e; }

在我的x86盒子上,一个FourBytes实例需要12个字节(包括开销).FiveBytes的实例需要16个字节.唯一的区别是"e"变量 - 那么需要4个字节吗?好吧,有点......而不是.显然,您可以从FiveBytes中删除任何单个变量以使大小减小到12个字节,但这并不意味着每个变量占用4个字节(考虑删除所有变量!).单个变量的成本并不是一个在这里很有意义的概念.


@jon - 我对你的帮助班感兴趣...可用吗?

2> angry person..:

根据被问者的需要,Marshal.SizeOf可能会或可能不会给你你想要的东西.(Jon Skeet发布他的回答后编辑).

using System;
using System.Runtime.InteropServices;

public class MyClass
{
    public static void Main()
    {
        Int32 a = 10;
        Console.WriteLine(Marshal.SizeOf(a));
        Console.ReadLine();
    }
}

请注意,正如jkersch所说,可以使用sizeof,但遗憾的是只能使用值类型.如果你需要一个班级的大小,Marshal.SizeOf就是你要走的路.

Jon Skeet已经阐明了为什么sizeof和Marshal.SizeOf都不是完美的.我想问题需要决定是否可以接受他的问题.



3> Jesper Niede..:

从他在答案中的Jon Skeets食谱中我试图制作他所指的帮助班.欢迎提出改进建议.

public class MeasureSize
{
    private readonly Func _generator;
    private const int NumberOfInstances = 10000;
    private readonly T[] _memArray;

    public MeasureSize(Func generator)
    {
        _generator = generator;
        _memArray = new T[NumberOfInstances];
    }

    public long GetByteSize()
    {
        //Make one to make sure it is jitted
        _generator();

        long oldSize = GC.GetTotalMemory(false);
        for(int i=0; i < NumberOfInstances; i++)
        {
            _memArray[i] = _generator();
        }
        long newSize = GC.GetTotalMemory(false);
        return (newSize - oldSize) / NumberOfInstances;
    }
}

用法:

应该使用生成T的新实例的Func创建.确保每次都不返回相同的实例.这没关系:

    public long SizeOfSomeObject()
    {
        var measure = new MeasureSize(() => new SomeObject());
        return measure.GetByteSize();
    }


@Alexey但你不想测量_memArray!它只是一个辅助数组,包含你想要测量的东西,即T的大小.这是这个类的重点.

4> Earlz..:

我不得不把它一直放到IL级别,但我终于把这个功能带到了一个非常小的库的C#中.

您可以在bitbucket获得它(BSD许可)

示例代码:

using Earlz.BareMetal;

...
Console.WriteLine(BareMetal.SizeOf()); //returns 4 everywhere I've tested
Console.WriteLine(BareMetal.SizeOf()); //returns 8 on 64-bit platforms and 4 on 32-bit
Console.WriteLine(BareMetal.SizeOf()); //returns 16 in some places, 24 in others. Varies by platform and framework version

...

struct Foo
{
  int a, b;
  byte c;
  object foo;
}

基本上,我所做的是围绕sizeofIL指令编写一个快速的类方法包装器.该指令将获得对象的引用将使用的原始内存量.例如,如果你有一个数组T,那么sizeof指令会告诉你每个数组元素之间有多少字节.

这与C#的sizeof运营商截然不同.首先,C#只允许纯值类型,因为它不可能以静态方式获得其他任何东西的大小.相反,该sizeof指令在运行时级别工作.因此,无论多少内存,都会返回在此特定实例期间将使用的类型引用.

您可以在我的博客上看到更多信息和更深入的示例代码

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有