如何在C#中打包小数据类型

时间:2012-06-21 14:56:09

标签: c# .net memory-management mono

我不打算提高性能或内存使用率,这个问题纯粹是出于好奇。

主要问题 鉴于以下类,C#编译器(Mono + .NET)将两个short变量打包成4个字节,还是消耗8个字节(带对齐)?

public class SomeClass {
    short a;
    short b;
}

次要问题 如果上述问题的答案不是4个字节,那么以下备选方案是否会提供任何优势(其中SomeClass的使用量非常大):

// Warning, my bit math might not be entirely accurate!
public class SomeClass {
    private int _ab;

    public short a {
        get { return _ab & 0x00ff; }
        set { _ab |= value & 0x00ff;
    }
    public short b {
        get { return _ab >> 8; }
        set { _ab |= value << 8; }
    }
}

3 个答案:

答案 0 :(得分:6)

这取决于运行时,正如@David_M所说,但您可以使用[StructLayout]属性强制它,该属性具有Pack成员,您可以使用该属性来控制打包。或者,您可以使用[FieldOffset]手动布局结构的成员(甚至重叠,这是您在.NET中实现联合的方式)。

答案 1 :(得分:5)

这取决于运行时,而不是编译器。您可以使用[StructLayout]覆盖默认行为,这可能有所帮助 - 尽管默认行为应该没问题。

话虽如此,如果绝对要求最小化总大小,您可能需要考虑struct而不是class。使用类时,类的每个实例都会增加很多开销。在syncblk,TypeHandle等之间,以及引用(在64位系统上是另外8个字节)对象实例使用相当数量的&#34;额外&#34;记忆超越你的两条短裤。有关详细信息,请参阅"How the CLR Creates Runtime Objects"

将数据存储到一组值类型中可以完全避免这种情况,并将实例总数保持在每个8字节(加上收集开销)。当然,这会改变使用方面的语义,但是如果你只使用两个短路,这将减少你的类型所涉及的开销量,特别是在64位系统上。

答案 2 :(得分:2)

实际布局取决于运行时,因为其他人已评论主要是因为您可以在多个平台上运行相同的代码。

是的,如果有很多物品可以节省空间。您正在寻找的是LayoutKind(StructLayout属性)。它可以让你随心所欲地打包成员。例如,使用Sequential,它将确保它紧凑。

[StructLayout(LayoutKind.Sequential)]
public class SomeClass {
    short a;
    short b;
}

有关详细信息,请查看MSDN- Structlayout