以前知道值分为值类型、引用类型,参数传递的时候分为值传递、引用传递,各种书里面、论坛、园里面都有各种解释,但是有些地方是一带而过,没有说很具体。下面就我个人理解说说,以前总是认为他们是有关系的,现在个人理解的是【值类型VS引用类型】 与【值传递VS引用传递】完全没得关系八竿子打不着的事儿。有不同意见的可以大家一起讨论
1、首先说说【值类型VS引用类型】:
值类型(形如:int、bool、struct等等)就是存储在堆栈(其实就是线程栈,基本就是用完了就被操作系统回收了),如上图值类型直接存储了值:A的值为5
引用类型(class 修饰的)是存储在托管堆的是GC来判定是否回收,如上图,堆栈里面其实就是存储的是一个托管堆的地址,当访问的时候会先找到01xx04这个地址,然后发现时引用类型并且指向托管堆地址为0Exx03,然后就可以访问对象中的x=1,y=2的值了。明显看出引用类型比值类型多了一道关卡,所以引用类型要慢一拍。
PS:再次强调【值类型VS引用类型】 与【值传递VS引用传递】其实是完全没有关系的
2、 然后就说说【值传递VS引用传递】:
简单点说吧,用ref 和out修饰参数的才是引用传递,其他都是值传递。
【值传递】:用值传递的时候形参会再次分配内存空间02xx02、02xx04,传递的值就是 5和0Exx03,所以形参接收过来就是a=5了,对象在堆栈中存储的就是0Exx03地址指向托管堆
【引用传递】:用引用传递的时候形参再次分配内存空间02xx02存储的01xx02,而02xx04存储地址01xx04,所以修改之后直接影响到了实参结果:x值变为了10000,而aClass指向了新的对象。(注意:有些人认为引用传时,ChangeRef 这里面的aClass不会影响Page_Load中的aClass,但事实是影响了。)
实验代码如下:
protected void Page_Load(object sender, EventArgs e) { int age; int iResult; int x=888; A aClass = new A(10); ChangeValue(x, aClass); age = aClass.Age;//2012 iResult = x;//888 ChangeRef(ref x, ref aClass); age = aClass.Age;//10000 iResult = x;//10000 int i = 0; } public void ChangeRef(ref int i, ref A aClass) { i = 10000; aClass = new A(10000);//这儿重新指向了一个对象,实参也指向了这个新的对象 } public void ChangeValue(int i, A aClass) { i = 2012; aClass.Age = 2012; } } public class A { public int Age; public A(int value) { Age = value; } }
以上纯属个人理解,完全是抛砖引玉,希望大家多多指点。