8.6.2 按引用传递参数——关键字:ref

和前面的“按值传递”相对应的是按引用传递。顾名思义,这里传的不再是值,而是引用,通过图8-9我们看到,实参myValue的值在方法执行以后并没有发生改变,原因就是在方法内部操作的不是myValue变量本身,而是它的“克隆”——value变量。那么,当我们想要myValue在方法执行之后也做了相应的改变,该如何去做呢?那就用到了本节要讲的内容:引用参数,也就是说,传递的是参数的引用而不是参数值。打个比方:你想要风筝,而我不是给你买一个跟我一模一样的风筝,我交给你的是风筝线,至于你对这只风筝如何处置,就看你的了,你所做的每一个动作都直接作用于风筝本身,而不是作用于和它一模一样的副本。要实现通过引用传递参数也不难,只需要在形参和实参前面都加上ref关键字即可,我们举个例子来看,如代码清单8-10:

代码清单8-10 按引用传递参数


1 using System;

2 public class MethodSample

3{

4 public static void Main()

5{

6 MethodSample ms=new MethodSample();

7 int x=5;

8 string s=“猜猜我会被改变吗?”;

9 ms.DoSomething(ref x,ref s);//实参前加ref关键字

10 Console.WriteLine("x={0},s={1}",x,s);

11}

12

13 public void DoSomething(ref int someValue1,ref string someValue2)//形参前加ref关键字

14{

15 someValue1=10;

16 someValue2=“我确实被改变了”;

17}

18}


如代码清单8-10所示,首先在方法声明的时候,在形参前加上ref关键字,如第13行所示。其次在调用方法时,在实参前加ref关键字,如第9行所示。这时传递的就是x和s变量的引用,而不是其值,上述代码的运行结果为:


x=10,s=我确实被改变了


那么,我们将上述按值传递参数的代码(见代码清单8-9)改为按引用传递(见代码清单8-11),来观察它们的异同。

代码清单8-11 按引用传递参数示例


1 public class MethodSample

2{

3 public static void Main()

4{

5 MethodSample ms=new MethodSample();

6 Rectangle rectangle=new Rectangle();

7 int myValue=10;

8 ms.CalculateArea(ref rectangle,ref myValue);

9}

10

11 public void CalculateArea(ref Rectangle rect,ref int value)

12{

13 rect.Length+=10;

14 rect.Width+=15;

15 rect.Area=rect.Length*rect.Width;

16 value++;

17}

18

19}

20

21 public class Rectangle

22{

23 public int Length=10;

24 public int Width=15;

25 public int Area;

26}


我们仍然把上述代码使用图8-10表示如下,然后再结合图示给大家做解释。

8.6.2 按引用传递参数——关键字:ref - 图1

图 8-10 按引用传递参数图示

下面我们对上述代码和图示做如下解释,见表8-3:

8.6.2 按引用传递参数——关键字:ref - 图2

由此我们可以得出以下结论:

❑按引用传递的参数,系统不再为形参在托管栈中分配新的内存;

❑此时,形参名其实已经成为实参名的一个别名,它们成对地指向相同的内存位置。