C# 引用类型作为函数参数时
在探讨本文的主题之前,先来介绍下C#中的值类型和引用类型
众所周知C#中有值类型和引用类型,值类型有基础数据类型(诸如int,double,bool等)、结构体、枚举,引用类型有接口、类、委托。
值类型全部在操作系统的栈空间中申请,而引用类型则在操作系统的堆空间中建立对象,然后在栈空间中申请一个指针指向这个对象的地址。
因此C#的引用类型其实就如同C++的指针类型。
下面我再来看看函数传参的问题。
早在C时代就有函数参数传值和传地址的概念,请记住在C#中函数参数默认都是传值。
- 对于值类型,函数是将实参变量的值在栈空间复制一份然后传给形参变量。所以在函数中对形参变量的更改不会对实参变量造成任何影响,因为函数的形参只是实参的副本。
- 而对于引用类型,由于实参变量和形参变量都是引用类型,它们都指向内存堆中的某一对象的地址,函数是将实参变量指向的地址值复制了一份给形参变量,由于形参变量和实参变量指向堆中同一地址,所以在函数中使用形参变量对所指向对象所做的更改也会在实参变量中反映出来。
所以不管是值类型还是引用类型在作为参数传进函数时,其实都是传的值,只不过引用类型传的是对象在堆中的的地址罢了。
而且从上面的定义可以看出C#中引用类型的变量用C++来说就相当于是该引用类型的指针,比如有类(引用类型)RefClass:
RefClass rc就相当于是C++上的RefClass *rc
在C#中使用rc.IntValue++;时,相当于C++的rc->IntValue++;
因为引用类型在函数传参时是传地址的,所以我脑袋里就形成了一种惯性思维,认为只要传进函数的是引用类型,那么在函数中做的任何更改都会反映到实参上。但是我发现并不完全是这样,下面给出个例子(注释内容为对应等效的C++代码):