c#值类型和引用类型
- C#中有值类型和引用类型两大类型,值类型是分配在线程的堆栈上的,没有垃圾回收。所有的值类型其实是继承自System.ValueType类型,而System.ValueType又继承自System.Object。
- 引用类型是分配在应用程序的堆上的,创建一个引用类型会在堆栈上创建一个指向该类型的引用即指针,并在堆上分配内存空间存储对象和一个方法表指针,一个SyncBlockIndex。通过方法表指针,我们可以通过实例对象来调用其上继承而来的虚方法,通过SyncBlockIndex可以利用System.Threading.Monitor类型来同步多个线程对它们的访问。
- 引用类型可以分为三个部分:
- 分配在堆栈上的指针
- 分配在堆上的内存空间
- 附加的方法表指针和SyncBlockIndex
值类型和引用类型之间有装箱和拆箱的联系,简单的说,值类型转换为引用类型就是装箱,反之,引用类型转换为值类型为拆箱。但是值得注意的是:装箱前是什么值类型,拆箱之后必须与之相一致,如:
1 static void main() 2 { 3 Int32 x=32; 4 Object o=x; //对x进行装箱,o指向被装箱的对象 5 Int16 y=(Int16)o; //对o进行拆箱,但是会抛出异常 6 } 7 //正确的写法是: 8 Int16 y=(Int16)(Int32)o; 9 //装箱前是什么值类型,拆箱之后一定是什么类型,否则会抛出异常。
装箱和拆箱的过程:
装箱:object o=x;这里执行了装箱,装箱的过程是这样的:首先将值类型的实例字段拷贝到托段堆上新分配对象的内存里,即将x=32拷贝到堆上,然后返回托管堆上新分配对象的引用。所以,装箱时分两步进行的,一:从堆栈上拷贝实例字段到托管堆上,二:返回新对象的地址,即引用。
拆箱:Int16 y=(Int16)(Int32)o;这里是拆箱,拆箱也是分两步进行的:首先获取引用对象的指针地址,然后将其堆上的字段拷贝到堆栈上。