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

Lea*_*yes 5 .net c# mono memory-management

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

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

public class SomeClass {
    short a;
    short b;
}
Run Code Online (Sandbox Code Playgroud)

次要问题 如果上述问题的答案不是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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dai*_*Dai 6

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


Ree*_*sey 5

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

话虽这么说,如果最小化总大小是绝对要求,你可能想要考虑struct而不是a class.使用类时,类的每个实例都会增加很多开销.在syncblk,TypeHandle等之间,以及引用(在64位系统上是另外8个字节)对象实例使用相当数量的"额外"内存超出你的两个短路.有关详细信息,请参阅"CLR如何创建运行时对象".

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