什么';这个C#struct的大小是多少?

什么';这个C#struct的大小是多少?,c#,struct,sizeof,C#,Struct,Sizeof,存储在列表中时是12字节还是16字节 C#中是否有sizeof函数?Marshal.sizeof() 尝试Marshal.SizeOf(typeof(DataPoint))它将是12个字节(4个用于float,8个用于DateTime); Marshal.SizeOf将返回16,因为默认打包是8字节对齐的。 是一篇关于结构和包装的好文章。它对实际发生的事情进行了全面的描述。看看@Hans Passant的答案,了解这个问题的有趣背景,特别是关于Marshal.Sizeof的局限性,CLR可以在内

存储在
列表中时是12字节还是16字节

C#中是否有sizeof函数?

Marshal.sizeof()

尝试Marshal.SizeOf(typeof(DataPoint))

它将是12个字节(4个用于float,8个用于DateTime);
Marshal.SizeOf
将返回16,因为默认打包是8字节对齐的。
是一篇关于结构和包装的好文章。它对实际发生的事情进行了全面的描述。

看看@Hans Passant的答案,了解这个问题的有趣背景,特别是关于
Marshal.Sizeof
的局限性,CLR可以在内存中自由地布局它认为合适的类型。所以不可能直接给出“尺寸”

但是,对于结构,可以使用以下命令限制CLR的自由:

  • 自动:运行时自动选择适当的布局
  • 顺序:对象的成员按顺序排列,并根据StructLayoutAttribute.Pack值对齐
  • 显式:显式控制每个成员的精确位置
C#编译器会自动将顺序布局类型应用于任何结构。在x86或x64机器上,Pack值默认分别为4或8。因此,结构的大小是8+4=12(x86和x64)



不相关的根据类型在内存中的布局,还可以使用。封送处理程序在封送类型时应用几个转换,因此结果并不总是与CLR对类型的布局方式相同。(例如,一个
bool
在内存中需要1个字节加对齐,而封送器将
bool
封送到4个字节。)

以下代码基于:

//
///计算给定托管类型的大小。速度慢,但可靠。不会给出与Marshal.SizeOf相同的结果
///注意:这与数组中这些类型之间的距离不同。这取决于对齐情况。
/// 
公共静态int ComputeSizeOf(类型t)
{
//所有这些只是为了调用一个操作码而没有参数!
var方法=新的DynamicMethod(“ComputeSizeOfImpl”、typeof(int)、Type.EmptyTypes、typeof(Util)、false);
var gen=method.GetILGenerator();
gen.Emit(操作码.Sizeof,t);
gen.Emit(操作码Ret);
var func=(func)method.CreateDelegate(typeof(func));
返回func();
}
我认为您可能想知道的问题不是类型的大小,而是列表中两个相邻元素之间的距离。这是因为正如其他人所提到的,对齐可以发挥作用


我认为解决该问题的最佳方法是使用,但很难正确使用,特别是因为
列表
没有公开支持数组

您可以为他的问题添加解决方案:16字节(8字节+4字节+4字节对齐)封送。SizeOf()不返回托管结构的大小,只返回其非托管版本。检查Steve的答案。我希望您知道,当放入列表时,此结构的每个实例都将被装箱,因此请为指针添加空格。@ToxicAvenger:当您将其放入
列表时,它不会被装箱。它将被装箱在
数组列表
列表
中。这更为具体,但可能是注释的副本。考虑到填充和任何其他对齐操作,使用IL
sizeof
指令可以获得结构的“最终”CLR大小。请参阅,了解如何使用它以及更多区别(注意:我编写了一个包装器库,可以从C#调用)
public struct DataPoint
{
    DateTime time_utc;
    float value;
}
        /// <summary>
        /// Computes the size of the given managed type. Slow, but reliable. Does not give the same result as Marshal.SizeOf
        /// NOTE: this is not the same as what is the distance between these types in an array. That varies depending on alignment.
        /// </summary>
        public static int ComputeSizeOf(Type t)
        {
            // all this just to invoke one opcode with no arguments!
            var method = new DynamicMethod("ComputeSizeOfImpl", typeof(int), Type.EmptyTypes, typeof(Util), false);
            var gen = method.GetILGenerator();
            gen.Emit(OpCodes.Sizeof, t);
            gen.Emit(OpCodes.Ret);
            var func = (Func<int>)method.CreateDelegate(typeof(Func<int>));
            return func();
        }