
原文: C#如何获取类型或类型实例对象的大小
计算类型或类型实例对象时发生异常:
“无法封送为非托管结构;无法计算有意义的大小或偏移量. ”
检查后,我们创建的结构或类都是复杂类型. (更正后,如果成员具有复杂的类型,并且占用了字节,则在运行时会使用Marhsal.SizeOf出现一些变量,这里也是无效的,仅统计非托管资源)
如果您未在其中设置某些成员的布局,则直接设置sizeof()或Marshal.SizeOf(对象),Marshal.SizeOf(类型)将报告此异常.
因此,我们需要根据需要设置成员布局,以便可以正常执行上述sizeof()或Marshal.SizeOf(对象),Marshal.SizeOf(类型).
1. 了解数据结构的布局
数据结构的布局,首先必须了解: (悲伤刷,百度不适合代码格式,或者CNBLOG很好)
//摘要:
//控制导出到非托管代码时对象的布局.
[可序列化]
[ComVisible(true)]
公共枚举LayoutKind
{
//摘要:
//对象的成员以它们导出到非托管内存时出现的顺序排列. 这些成员基于System.Runtime.InteropServices.StructLayoutAttribute.Pack
中指定的软件包

//的布局可以不连续.
顺序= 0,
//
//摘要:
///显式控制对象在非托管内存中每个成员的确切位置. 每个成员都必须使用System.Runtime.InteropServices.FieldOffsetAttribute
//指示字段在类型中的位置.
显式= 2,
//
//摘要:
//运行时自动为非托管内存中的对象成员选择适当的布局. 使用此枚举成员定义的对象不能在托管代码之外公开. 尝试这样做将引发异常.
自动= 3,
}
顺序是有序的,但不是连续的. 通常我们使用这个.
显式这没什么用,因为该成员在内存块中的位置是精确定位的.
汽车我对上述“正确的布局”了解不多. 如果将其用于布局,我上面提到的异常将直接出现:
“无法封送为非托管结构;无法计算有意义的大小或偏移量. ”
2. 了解如何布置复杂类型(类属性)

要布置复杂的类型,可以使用该类的属性来设置Attribute基类或其派生类. StructLayoutAttribute即可. 他是Attribute的派生类
//摘要:
// StructLayoutAttribute类允许用户控制类或结构的数据字段的物理布局.
[ComVisible(true)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,Inherited = false)]
公共密封类StructLayoutAttribute: 属性
从上面的定义描述中,我们可以知道StructLayoutAttribute是我们想要的类属性,“以控制类或结构的数据字段的物理布局”
3. 演示测试:
首先: 自动
[StructLayout(LayoutKind.Auto)]
A级
{
公共短a = 0;
public int b = 0;
公共长c = 0;
}
A a = new A();

int asize = Marshal.SizeOf(a.a); //直接抛出异常
int bsize = Marshal.SizeOf(a.b);
int csize = Marshal.SizeOf(a.c);
int allsize = Marshal.SizeOf(a);
MessageBox.Show(string.Format(“ a.Size: [{0}],b.Size: [{1}],c.Size: [{2}],总计: [{3}]” ,asize获取类型c#,bsize,csize,allsize));
第二个: 显式
[StructLayout(LayoutKind.Explicit)] //要使用Explicit,必须对成员的大小或偏移量进行精确设置. 仅汗水,不建议每个成员
A级
{
[FieldOffset(0)] //仅当布局枚举项为LayoutKind.Explicit时才可以使用字段偏移设置
公共短a = 0;
[FieldOffset(2)]
public int b = 0;
[FieldOffset(6)]
公共长c = 0;
}
A a = new A();

int asize = Marshal.SizeOf(a.a); //如果没有FieldOffset的成员设置,则会直接引发异常
int bsize = Marshal.SizeOf(a.b);
int csize = Marshal.SizeOf(a.c);
int allsize = Marshal.SizeOf(a);
MessageBox.Show(string.Format(“ a.Size: [{0}],b.Size: [{1}],c.Size: [{2}],总计: [{3}]” ,asize,bsize,csize,allsize));
第三: 顺序
[StructLayout(LayoutKind.Sequential)] //顺序是有序的,但不是连续的. 至于他为什么能够成功获取类型c#,我也希望Daniel指出其内部原理和sizeof配置.
A级
{
公共短a = 0;
public int b = 0;
公共长c = 0;
}
A a = new A();
int asize = Marshal.SizeOf(a.a); //直接成功
int bsize = Marshal.SizeOf(a.b);
int csize = Marshal.SizeOf(a.c);
int allsize = Marshal.SizeOf(a);
MessageBox.Show(string.Format(“ a.Size: [{0}],b.Size: [{1}],c.Size: [{2}],总计: [{3}]” ,asize,bsize,csize,allsize));
如图所示:
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-154653-1.html
哎呀杨洋啊