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-10 按引用传递参数图示
下面我们对上述代码和图示做如下解释,见表8-3:
由此我们可以得出以下结论:
❑按引用传递的参数,系统不再为形参在托管栈中分配新的内存;
❑此时,形参名其实已经成为实参名的一个别名,它们成对地指向相同的内存位置。