C#类型派生谱系
- C#语言五大基本类型:
1.类类型:由class关键字声明的类型,常见的类类型有:string,object
2.结构体类型:由struct关键字声明的类型,常见的结构体类型有:int,uint,long,ulong,bool,short,ushort,char等等
3.枚举类型:由enum关键字声明的类型
4.委托类型:由dalegate关键字声明的类型
5接口类型:由interface关键字声明的类型
再进一步归类,类,委托,接口属于引用类型,结构体,枚举属于值类型,而所有类型的终极基类都是object类
- 变量:初识变量时,其仅仅就是数据的容器,用于存放数据的,但是其实变量代表了内存中的某一块空间,变量是指从变量名所代表的内存地址开始,以数据类型所要求的数据长度为大小的一块内存空间;而这块内存空间要么用于存放值,要么用于存放一个地址,若这块内存空间用于存放的是值,那么该变量就是值类型的变量,若此块内存空间用于存放的是一个内存地址,那么该变量就是一个引用类型的变量;
变量的分类:局部变量,静态变量,实例变量,数组元素变量,值类型参数变量,引用类型参数变量,输出参数变量 局部变量:定义在函数中的变量 静态变量:即静态子段,在定义在类中,以static关键字进行修饰的变量,静态变量是属于类的,而不是属于某一个具体的类实例 实例变量:定义在类中,无static关键字修饰的变量,其属于实例,而不属于类 数组元素变量:即数组元素 值类型参数变量:是函数的形式参数,无任何修饰符修饰的形式参数 应用类型参数变量:以关键字ref进行修饰的函数的形式参数变量 输出类型参数变量:以关键字out进行修饰的函数的形式参数变量
- 值类型:值类型的变量与引用类型的变量的区别是,值类型的变量所对应的内存空间里面存放的是值类型变量的值;以int类型为例,讲解值类型变量在内存空间中是如何存放的
上一篇博文中我们提到过,程序要运行的话,必须从磁盘上读取到内存中,才可以运行,而内存被分为了三大部分:操作系统占用的内存空间,栈空间,堆空间,操作系统占用的内存空间不可被访问,程序读取到内存中时占用的是栈空间和堆空间;内存按字节编址,其为每一个字节空间都指定了一个独立的编号,也就是编址,当我们想要访问某一块内存空间中的值时,需要先拿到该内存空间的地址,这就是寻址过程,以下用excel表格来模拟内存空间:
那么细心的人也许会想:程序的不同组成部分到底具体存放在堆空间中呢,还是存放在栈空间中,上一篇博文中我们提到,程序中出现的方法在运行时存放在栈空间中,相应的在方法中定义的局部变量,函数参数等都会存放在栈空间中,而对象也就是实例是存放在堆空间中的,以如下程序讲解值类型变量在内存空间中是如何存放的:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace course { class Program { static void Main(string[] args) { int a = 100; } } }
在上面的代码中我定义了一个值类型的变量a,并为其赋值100,因为a定义在Main函数中,所以其属于局部变量,那么,当程序运行时a会被存放在内存中的栈空间上,当程序读入内存中时,内存会先看变量定义,发现该变量是局部变量,且a是int类型的,那么系统就会在内存的栈空间中找到连续的4个字节的空闲栈空间
如图,假设103~106是空闲的,那么系统就将该块内存空间分给变量a,然后在该块内存空间中存放变量a的实际值,当然要将实际值转换成二进制数在放入内存中,所以内存中该块区域存放的实际值为:
int类型占4个字节,即32bit,将100转换成二进制时不足32位的高位补0补足32位,注意内存中存放数据值时,遵循高位存放在高地址,地位存放在低地址的原则; 以如下程序讲解引用类型的变量在内存空间中是怎样存放的:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace course { class Program { static void Main(string[] args) { Example e; e = new Example(); } } class Example { int a; char b; } }
在上面的程序中我定义了一个叫做Example的类,类中定义了两个实例变量,分别为int型和char型,int型占4个字节,char型占用2个字节;在Main方法中我声明了一个局部变量e,当程序读入内存时,系统会在栈空间找一个空闲的内存块分配给变量e,而变量e是引用类型的变量,系统会为引用类型的变量分配固定的4字节的内存空间,
假设110~113栈空间是空闲的,那么此时变量e得到的内存空间就是紫色区域,在该空间中存放的是什么呢?前面我们提到引用类型变量存放的是一个地址,存放的是什么地址呢,接着往下看,e = new Example(); 该程序语句为Example类创建了一个实例或者说是对象,而实例是存放在堆内存空间中的,所以此时系统去堆空间中找一块空闲的内存块分配给该实例,而该实例应该占据6个字节,假设305~310是空闲的,系统将其分配给该实例,
前四个字节存放int型的实例属性a,后两个字节存放char型的实例属性b ,所以引用类型的变量e所代表的内存空间中存放的地址就是实例对象在堆空间中的首地址305,当然需要将305转换成二进制再存放到e所指向的空间中;
由于我没有给实例属性赋值,所以系统自动为其赋值为0;而实例属性类型都是值类型,所以相应的实例变量所对应的内存空间中存放的内容都是实例的值;