标签:
原文:C#中值类型和引用类型本文将介绍C#类型系统中的值类型和引用类型,以及两者之间的一些区别。同时,还会介绍一下装箱和拆箱操作。
首先,我们看看在C#中哪些类型是值类型,哪些类型是引用类型。
值类型:
引用类型:
变量的初始化中,都会有一个默认值,在C#中,我们可以通过default关键字去查看某个类型的默认值。
通过default(int)可以看到,int的默认值是0,default(bool)显示布尔类型的默认值是false。
对于所有的引用类型,默认值都会是null。
注意,这里有个特殊的情况就是结构struct,如果对一个结构进行default操作,我们将得到每个结构成员的初始值状态。也就是说,值类型成员赋予值类型的默认值,引用类型成员赋予引用类型的默认值。
下面,我们通过一个简单的例子看看。假设有一个Point类型,有x和y两个坐标成员。
同样是下面一段代码
Point p1 = new Point(5,9); Point p2 = p1;
如果Point类型是通过结构struct实现,那么p2将会是p1的一个副本,也就是说任何一个的修改都不会影响另外一个;如果Point类型是通过类class实现,那么p2和p1的引用值将会指向同一个对象。
为了进一步了解值类型和引用类型,我们需要介绍一下栈和堆这两个基本概念。
当我们在32为系统上运行一个程序的时候,这个程序就会有一个4GB的进程运行空间。我们所要讨论的栈和堆就存放在这个4GB的空间中。
在C#中,栈(Stack)是指堆栈;堆(Heap)是指托管堆,由.NET垃圾收集器自动管理。
这里就不对栈和堆进行详细的分析了,只是举一个简单的例子来大致描述栈和堆的工作原理。
从图中可以看到,局部变量在栈上的变化(入栈),当函数执行结束后,栈上的空间将会被清理;但是我们在堆上分配的空间始终从在,只能等待GC去帮我们清理不会被引用到的空间。
介绍过栈和堆之后,下面我们看看值类型和引用类型是怎么存放的。
对于值类型的变量,这个变量本身就代表这个值类型的值;但是,对于引用类型的变量,这个引用类型的实例是在托管堆上分配的空间,而这个变量本身只是代表一个指向托管堆实例的引用(指针)。
所以这里,我们可以对值类型和引用类型变量的存储有两个概括:
注意:根据上面第二点概括,可以得到"值类型一定存储在栈中"这个说法是错误的。例如,我们有一个Student类,在这个类中的Age属性是一个值类型,但是这个值类型是存储在Student类实例的空间中,也就是在堆上。
class Student { public string Name { get; set; } public int Age{ get; set; } }
由于C#中所有的数据类型都是由基类System.Object继承而来的,所以值类型和引用类型的值可以通过显式(或隐式)操作相互转换。
这里,可以将装箱和拆箱描述为:
其实,在装箱和拆箱的过程中都对应一系列的转换,这里就通过下图表示了。
在值类型进行装箱时,生成的是全新的引用对象,这会有时间损耗,也就是造成效率降低。所以在C# 2.0中就引入了泛型来减少装箱操作和拆箱操作消耗。
本文介绍了C#中的值类型和引用类型,以及栈和堆的基本概念。然后分析了值类型和引用类型在栈和堆中的存放。
同时,我们也了解到了:
标签:
原文地址:http://www.cnblogs.com/lonelyxmas/p/4287313.html