前言
C#的类型系统可分为两种类型,一是值类型,一是引用类型。在C#中每种类型的存储方式又分为两种,一是分配在托管栈中(简称栈),一是分配在托管堆中(简称堆)。内存的分配有CLR管理,即CLR(公共语言运行库,Common Language Runtime)和Java虚拟机一样也是一个运行时环境,是一个可由多种编程语言使用的运行环境。
数据类型
1、概念
值类型:数据存储在内存的堆栈中,从堆栈中可以快速的访问这些数据,因此,值类型表示实际的数据。
引用类型:表示指向存储在内存堆中的数据的指针或引用
栈:栈是编译期间就分配好的内存空间,因此代码中必须就栈的大小有明确的定义。分配在托管栈中的变量会在创建它们的方法返回时自动释放。
堆:堆是程序运行期间动态分配的内存空间,可以根据程序的运行情况确定要分配的对内存的大小。分配在托管堆中的变量并不会在创建它们的方法结束时释放内存,它们所占用的内存会被CLR中的垃圾回收机制释放。
2、区别
基本区别在于它们的存储方式,值类型只将值存放在内存中,这些值类型都存储在堆栈中。而引用类型的内存单元只存放内存堆中对象的地址,而对象本身放在内存堆中。
值类型直接从堆栈中里面取值,而引用类型必须要先从堆栈里面取出它的地址,再根据这个地址在堆里找到对应的值。
3、分类
4、举例
举例对象为结构和类,结构属于值类型,类属于引用类型。
第一步:创建p1和p2,给p1赋值,然后让p2=p1,代码如下:
对于上述代码,放在结构和类中,运行结果是一样的,结果如下:
解释:
结果一样,但是理念不一样。在结构中,栈中存放的就是值,p1和p2在栈中都有各自的内存空间,p2=p1,是将p1的值赋值给p2。在类中,p1和p2在栈中存放的各自的地址,在堆中存放的是值,p2=p1,不是将p1的值赋给p2,而是表示p2和p1一样,将指针指向堆中的值。
第二步:在给p2赋新值,同样的代码放在结构和类中,结果是不一样的:
(1)如果代码是放在结构中,结果如下:
解释:
在结构中,即对于值类型,在变量p1、p2创建时已分配好了内存空间,所以在给p2赋新值前,p1和p2各自空间中的值是相同,当给p2赋新值后,p1空间的值不会改变,只是把p2原先的值给替换了,所以,结果是
(2)如果代码是放在类中,结果如下:
解释:
在类中,即对于引用类型,栈中存放的地址,p1和p2有不同的地址,值存放在堆中(为引用类型对象赋值时,似乎是引用类型必须要先从堆栈里面取出它的地址,再根据这个地址在堆里找到对应的值。)。p1=p2,代表他俩的地址会指向相同的值,当给p2赋新值后,p2会指向新值,因为p1和p2的地址相同,所以p1也会指向新值。所以结果相同。
小结