在统计类型或类型实例对象时,出了个异常:

“不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。”

后来查了一下,原来,我们创建的struct或是class都是属于复杂类型的。(纠正一下,如果成员又有复杂类型的,而所占字节,在运行时,会有所变量,在这使用Marhsal.SizeOf也是无效的,只能对非托管资源的一个统计)

如果不对其内部的一些成员布局设置,直接sizeof()或是Marshal.SizeOf(object), Marshal.SizeOf(Type)是会报这个异常的。

所以我们要按需去对成员布局设置一下就可以让上面的sizeof()或是Marshal.SizeOf(object), Marshal.SizeOf(Type)正常执行。

1、了解数据结构布局

数据结构布局嘛,就肯定先得了解:(悲刷,百度不适合搞代码格式,还是CNBLOG好)

// 摘要:

//     控制当导出到非托管代码时对象的布局。

[Serializable]

[ComVisible(true)]

public enum LayoutKind

{

// 摘要:

//     对象的成员按照它们在被导出到非托管内存时出现的顺序依次布局。这些成员根据在 System.Runtime.InteropServices.StructLayoutAttribute.Pack

//     中指定的封装进行布局,并且可以是不连续的。

Sequential = 0,

//

// 摘要:

//     对象的各个成员在非托管内存中的精确位置被显式控制。每个成员必须使用 System.Runtime.InteropServices.FieldOffsetAttribute

//     指示该字段在类型中的位置。

Explicit = 2,

//

// 摘要:

//     运行库自动为非托管内存中的对象的成员选择适当的布局。使用此枚举成员定义的对象不能在托管代码的外部公开。尝试这样做将引发异常。

Auto = 3,

}

Sequential 有序,可不连续,一般我们用这个。

Explicit 这个比较少用,因为都是对成员在内存块中的位置在精确的定位的。

Auto 这个不是很了解其上述所说的“适当的布局”,如果用这个来布局,会直接出现我上面所说的异常:

”不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。“

2、了解怎么对复杂类型布局(类属性)

要对复杂类型布局,要用到类的属性设置Attribute基类或是其派生类都可以。StructLayoutAttribute可以。他是Attribute的派生类

// 摘要:

//     StructLayoutAttribute类使用户可以控制类或结构的数据字段的物理布局。

[ComVisible(true)]

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]

public sealed class StructLayoutAttribute : Attribute

从上述定义描述,可以知道StructLayoutAttribute 就是我们想要的类属性,"以控制类或结构的数据字段的物理布局"

3、DEMO测试:

第一种:Auto

[StructLayout(LayoutKind.Auto)]

class A

{

public short a = 0;

public int b = 0;

public long 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}], totale : [{3}]", asize, bsize, csize, allsize));

第二种:Explicit

[StructLayout(LayoutKind.Explicit)]//用到Explicit,必须要对成员的大小或是偏移量,有个精确的设置才成员,汗一下,对每个成员喔,不建议使用这个

class A

{

[FieldOffset(0)]//只能配合布局枚举项为LayoutKind.Explicit时,才可以使用字段偏量设置

public short a = 0;

[FieldOffset(2)]

public int b = 0;

[FieldOffset(6)]

public long 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}], totale : [{3}]", asize, bsize, csize, allsize));

第三种:Sequential

[StructLayout(LayoutKind.Sequential)]//Sequential有序,可不连续,至于他为啥可以成功,我还想让大牛指点其内部与sizeof配置使用的原理。

class A

{

public short a = 0;

public int b = 0;

public long 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}], totale : [{3}]", asize, bsize, csize, allsize));

如图:

C# 如何获取某个类型或类型实例对象的大小的更多相关文章

  1. block本质探寻五之atuto类型局部实例对象

    说明:阅读本文章,请参考之前的block文章加以理解: 一.栈区block分析 //代码 //ARC void test1() { { Person *per = [[Person alloc] in ...

  2. springboot启动流程(一)构造SpringApplication实例对象

    所有文章 https://www.cnblogs.com/lay2017/p/11478237.html 启动入口 本文是springboot启动流程的第一篇,涉及的内容是SpringApplicat ...

  3. C#动态创建接口的实现实例对象

    本文简单介绍如何动态创建接口interface的实现实例对象,包含两个知识点: 1.如何获取接口interface的所有实现实例对象? 2.如何判断实例对象的构造函数是否有参数? 准备工作 首先新建一 ...

  4. C# 获取与解析枚举类型的 DescriptionAttribute

    原文:C# 获取与解析枚举类型的 DescriptionAttribute System.ComponentModel.DescriptionAttribute 这个 Attribute,经常被用来为 ...

  5. Gson通过借助TypeToken获取泛型参数的类型的方法

    最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使 ...

  6. Gson通过借助TypeToken获取泛型参数的类型的方法(转)

    最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使 ...

  7. java入门---变量类型&类变量&局部变量&实例变量&静态变量

        在Java语言中,所有的变量在使用前必须声明.声明变量的基本格式如下:     type identifier [ = value][, identifier [= value] ...] ; ...

  8. SpringBoot27 JDK动态代理详解、获取指定的类类型、动态注册Bean、接口调用框架

    1 JDK动态代理详解 静态代理.JDK动态代理.Cglib动态代理的简单实现方式和区别请参见我的另外一篇博文. 1.1 JDK代理的基本步骤 >通过实现InvocationHandler接口来 ...

  9. struts文件上传,获取文件名和文件类型

    struts文件上传,获取文件名和文件类型   Action中还有两个属 性:uploadFileName和uploadContentType,这两个属性分别用于封装上传文件的文件名.文件类型.这是S ...

随机推荐

  1. HDOJ(1001) Sum Problem

    这一套题做错了几次,按理说直接用等差数列求和公式就行了,主要是要考虑一些运算符的结核性问题: 四则运算符(+.-.*./)和求余运算符(%)结合性都是从左到右. 于是,我自己写了一个版本,主要是考虑( ...

  2. linux共享文件samba安装与java读取外部文件夹方法

    测试环境RedHat 6.4 一.安装 samba组件安装: (1)首先用“rpm –qa |grep samba”命令检验系统samba服务是否安装. #rpm –qa |grep samba sa ...

  3. linux (centos 6.4)安装自定义分区方案(转载)

    在计算机上安装 Linux 系统,对硬盘进行分区是一个非常重要的步骤,下面介绍几个分区方案. 方案 1 / :建议大小在 5GB 以上. swap :即交换分区,建议大小是物理内存的 1~2 倍. 方 ...

  4. (转载)SQL中导入图片

    SQL中导入图片 分类: 论坛精贴 2006-05-10 12:07 398人阅读 评论(0) 收藏 举报 sqlimage服务器insertlogingo 1.建立过程CREATE PROCEDUR ...

  5. ExtJS4加载FormPanel数据的几种方式

    我们做web应用最多的就是处理表单,extjs为我们提供了很多处理表单的功能,很多初学者疑惑怎么加载表单数据,到底能用什么方式加载?本文中,我将我自己实验过的进行一下总结,自己备忘,也希望能帮助到其他 ...

  6. 用python实现k近邻算法

    用python写程序真的好舒服. code: import numpy as np def read_data(filename): '''读取文本数据,格式:特征1 特征2 -- 类别''' f=o ...

  7. C# - 接口,继承

    接口 接口是把公共实例(非静态)方法和属性组合起来,以封装特定功能的一个集合.不能像实例化一个类那样实例化接口.接口不能包含实现其成员的任何代码,而只能定义成员本身.实现过程必须在实现接口的类中完成. ...

  8. SQL 返回数量一定的行

    1. 限制返回的行 select top 10 * from tablename 2. 返回随机n行 select top n * from tablename order by newid()

  9. bp神经网络算法

    对于BP神经网络算法,由于之前一直没有应用到项目中,今日偶然之时 进行了学习, 这个算法的基本思路是这样的:不断地迭代优化网络权值,使得输入与输出之间的映射关系与所期望的映射关系一致,利用梯度下降的方 ...

  10. [转载]常用Web Service汇总(天气预报、时刻表等)

    下面总结了一些常用的Web Service,是平时乱逛时收集的,希望对大家有用. ============================================ 天气预报Web Servic ...