聊聊参数传递

前阵子有人问了这样一道问题,就是说,明明类是引用类型,为什么传递进方法之后的改变不会改变到Main方法里面的值。

从这里,我想有必要解释一下。

首先传递一般有四种情况,值类型按值传递,值类型按引用传递,引用类型按值传递,以及引用类型按引用传递。


我们先看下面的代码:

Code

 

 如上所示,我们可以看到两种传递情况:

 

public void second(Value v, int i)

 

分别是:引用类型按值传递,跟值类型按值传递,

首先值类型按值的传递很多人都了解,过程是:

发生方法调用时,CLR 生成了一个相对应的副本,并将该副本传递进方法中,以后的修改都只针对副本,而不会改变原来的值。

 

然后我们详细讨论一下,引用类型的传递。

 

同样的,当我们调用下面的方法时;

 

public void second(Value v, int i)

 

很多人就会问,引用类型传递的不是他本身吗?其实这里有个误区,引用类型传递的是引用而不是他本身,

 

就像这样:

 public void second(Value V, int i)
        {
            i 
= 0;
            V.i 
= 20;
            Value val 
= new Value();
            V 
= val;
            Console.WriteLine(v.i 
+ " " + i + " ");
        }

 

 

在这个方法体中,我们可以用一个v来代替传递进来的Value;其实发生的是这样的一种情况,

方法开始时,CLR为我们创建了一个

Value V = 传递进来的v

 

画成图应该是这样:

 

然后方法调用的时候,产生了一个vcopy,就是V,也指向托管堆中v的确切数据。

 

然后我们看到了方法体中这样的代码:

 V.i = 20;
   Value val 
= new Value();
   V 
= val;

 

首先因为V现在是指向 v的确切数据的, 所以V.i = 20 改变了外面v.i的值。

很多人就在这里迷惑了,觉得,这时方法外的v也会因为Value的构造函数,而变成15

但事实是那个我们在内存里发生的却是这样的情况:

 

因为Value val = new Value();

产生了一个新的对象,并由Val指向它。

 

接着,又因为以下代码,: V = vla;    使得V 指向了val所在的数据

 

 

最后,因为val 只是个局部变量,在方法结束后他就会结束它的生命周期,等待垃圾回收。

 

暂时讲到这里,太长了下回待续。>_< 欢迎各位敲砖~

 

 

 

 

 

 

 

posted on 2009-05-11 20:50  兴说:  阅读(295)  评论(0)    收藏  举报