最近在学习C#的过程中,对C#中关于值类型(Value Type)和引用数据类型(Reference Type)的一点思考与总结,现总结如下:
我们知道,一个健全的、可以运行的程序在书写时主要有三个阶段:编辑期、编译期以及调试运行期。在编辑期主要做的工作就是声明变量,创建实例等等程序代码的书写,那么在编译期,代码将被编译为Microsoft 中间语言,即MSIL(Microsoft Intermediate Language)。在代码被编译的过程中,将涉及的内存的分配问题,这就涉及的到了本文的主题:值类型和引用类型(Value Type and Reference Type)之间的区别。那他们之间究竟有什么区别呢?
首先,我们应该弄明白什么是值类型?什么是引用类型?
从概念上看,值类型和引用类型的区别是值类型直接存储其值,而引用类型存储对值的引用。这两种类型存储在内存的不同的地方:值类型存储在堆栈中,引用类型存储在托管堆上。也就是说值类型和引用类型的区别在于物理存放逻辑上,关于值类型,找到内存中对应的位置就找到了该变量的值,即值类型的变量和实例是放在一起的(都在栈里)。而引用类型变量放在栈里,存放的是对实例的引用地址,实例则存放在托管堆中。
明白了这两种类型之间的区别,让我们更深入的了解一下关于数据类型,如下图表示的是类型层次结构图:
关于类型层次结构图的解释如下:
这里有几点需要特别注意:
1.变量永远存放在栈里,无论是值类型的还是引用类型的变量。
2.在C#中,如果一个变量是一个引用,就可以将其值设为null,表示不引用任何对象。
3.在C#中预定义的值类型:
a. 整型:sbyte、short、int、long、byte、uint、ulong
b. 浮点类型:floot(32bit)、double(64bit)
c. decimal类型:decimal(128bit)
d. bool类型:bool(其值在C#中只能是true或false)
e. 字符类型: char(在C#中,此类型是16bit,为防止char类型与8bit的byte类型隐式转换,char类型的字面量是用单引号引起来的,而双引号中的值IDE会认为是字符串,会认为错误,并且C#中有一个string类型,不需要将字符串表示为char类型的数组)。
4. 其它的值类型:struct(结构体)、eunm(枚举类型)。
5. 在C#中预定义的应用类型:
a. object:跟类型、父类型,所有的内置类型和用户定义的类型均从它派生,最基本的方法:Equal()、GetHashCode()、GetType()、ToString()。
b. string:是一个很特殊的类型,它是值类型的赋值,但是却是一个引用类型。虽然是引用类型但是与其他的引用类型在常见的操作上有些区别,例如修改其中的一个字符串,就会创建一个全新的string对象,而之前的字符串还会存在于堆中,并且引用的的其它字符串不会受到影响而发生改变。
6. 其它的引用类型:Class(类)、Interface(接口)、Delegate(委托)。
7. 小结:在C#中值类型一共有15个,即机构体、枚举类型以及除string类型之外的所有内嵌数据类型。而引用类型可以理解为包括类以及类的衍生物。