C#为不同的类生成了type
实例,type
中记录每个类的描述数据,例如: 数据成员的名字、类型、偏移地址,函数的名字、类型、偏移地址。。。
于是我们可以通过type
到的一个类拥有的所有信息。
1.C#对象的内存布局
类:是一种类型描述,描述了这个类型有哪些数据组成,同时描述一些成员函数;
类的实例: new 类()
是具体的内存对象,相当于一块内存,包含了其数据成员的集合
2.类的成员函数
类的成员函数属于代码指令,编译完成以后,会编程代码指令,全局只有一份,所有的类的实例共用一份代码指令,存入到我们的代码段。
编译器---》代码---》.exe执行文件----》运行这个文件
的时候,会把里面的所有代码加载到内存的代码段;
1 | public class person{ |
在类的实例中,类的数据成员的所有数据包括看得见的数据name
age
,也有看不见你的数据,内存对齐
一个类定义好后,编译器将会记录类中成员的偏移地址(相对与类实例),这样通过类的实例也就可以得到他的成员变量。
同时,也会记录成员函数在代码段的偏移
3.反射如何记录类的信息
任意的类,都可以转化成这样一种描述:
类的实例是一个内存块,内存块的大小就是这个类的所有数据成员的大小。
我可以把这些数据成员的名字、类型、偏移地址通过数组等其它方式保存起来。
类数据成员数组:
1 | [{"name", type string,在对象偏移8个字节} |
类成员函数:
1 | [{"test1", 成员函数(静态函数),在代码段的位置} |
4.为什么需要反射
我们需要统一的方法来描述不同的类:
比如在制作Excel转ScriptObject或者直接将Excel的数据给到一个类,我们不可能事先知道有哪些类,也不能知道类的成员有哪些,只能通过反射根据Excel中定义的字符串来得到对应的类。
5.Type、Assembly是什么
通过上面的信息记录,编译器知道每个类的内存地址,类的各个成员的偏移地址
当运行的息时候C#会为不同的类生成这样的描述信息Type
实例,相同的类共享一份这个实例,于是我们可以通过这个类的Type
得到这个类的一切信息。
1 | public class Field{ |
通过Type
构建类的实例
Assembly
程序集中保存了所有的类,并且用类名与type
做映射,通过Assembly
可以通过字符串得到对应类的描述信息。
type
中记录了类的内存大小,于是可分配对应空间给类作为实例。
type
中记录了类的函数偏移地址,可以调用他的构造函数之类的。
type
中记录了类的字段的偏移地址和大小,可以为变量赋值。