ref的使用
ref 关键字在 C# 中经常使用,但是一直也没有认真考虑过它的确切含义。经常写代码,然而最基本的都还没有搞清楚,真是惭愧呀 :( 以前觉得使用 ref 是传的引用,如果在此方法里面更改参数的值,那此参数对应的变量的值也会被更改。
注:没有REF的方法调用的只是参数的一个副本,有ref传入的时候,是调用的一个引用。
下面的代码是 MSDN 上的例子:
1 // cs_ref.cs
2 using System;
3 public class MyClass
4 {
5 public static void TestRef(ref char i)
6 {
7 // The value of i will be changed in the calling method
8 i = 'b';
9 }
10
11 public static void TestNoRef(char i)
12 {
13 // The value of i will be unchanged in the calling method
14 i = 'c';
15 }
16
17 // This method passes a variable as a ref parameter; the value of the
18 // variable is changed after control passes back to this method.
19 // The same variable is passed as a value parameter; the value of the
20 // variable is unchanged after control is passed back to this method.
21 public static void Main()
22 {
23
24 char i = 'a'; // variable must be initialized
25 TestRef(ref i); // the arg must be passed as ref
26 Console.WriteLine(i);
27 TestNoRef(i);
28 Console.WriteLine(i);
29 }
30 }
2 using System;
3 public class MyClass
4 {
5 public static void TestRef(ref char i)
6 {
7 // The value of i will be changed in the calling method
8 i = 'b';
9 }
10
11 public static void TestNoRef(char i)
12 {
13 // The value of i will be unchanged in the calling method
14 i = 'c';
15 }
16
17 // This method passes a variable as a ref parameter; the value of the
18 // variable is changed after control passes back to this method.
19 // The same variable is passed as a value parameter; the value of the
20 // variable is unchanged after control is passed back to this method.
21 public static void Main()
22 {
23
24 char i = 'a'; // variable must be initialized
25 TestRef(ref i); // the arg must be passed as ref
26 Console.WriteLine(i);
27 TestNoRef(i);
28 Console.WriteLine(i);
29 }
30 }
输出结果是:
b b
在上面的例子中,是使用值类型作为参数的。那如果使用对象作为参数,会是什么样的呢?请看下面的代码:
1 // cs_object_ref.cs
2 using System;
3
4 public class MyObject
5 {
6 public int Data;
7 }
8
9 public class MyClass
10 {
11 public static void TestRef(ref MyObject m)
12 {
13 // The value of MyObject.Data will be changed in the calling method
14 m.Data = 10;
15 }
16
17 public static void TestNoRef(MyObject m)
18 {
19 // The value of MyObject.Data will be unchanged in the calling method
20 m.Data = 20;
21 }
22
23 public static void TestCreateRef(ref MyObject m)
24 {
25 m = new MyObject();
26 m.Data = 100;
27 }
28
29 public static void TestCreateNoRef(MyObject m)
30 {
31 m = new MyObject();
32 m.Data = 200;
33 }
34
35 public static void Main()
36 {
37
38 MyObject m = new MyObject();
39 m.Data = 1;
40
41 TestRef(ref m);
42 Console.WriteLine(m.Data);
43
44 TestNoRef(m);
45 Console.WriteLine(m.Data);
46
47 TestCreateRef(ref m);
48 Console.WriteLine(m.Data);
49
50 TestCreateNoRef(m);
51 Console.WriteLine(m.Data);
52 }
53 }
2 using System;
3
4 public class MyObject
5 {
6 public int Data;
7 }
8
9 public class MyClass
10 {
11 public static void TestRef(ref MyObject m)
12 {
13 // The value of MyObject.Data will be changed in the calling method
14 m.Data = 10;
15 }
16
17 public static void TestNoRef(MyObject m)
18 {
19 // The value of MyObject.Data will be unchanged in the calling method
20 m.Data = 20;
21 }
22
23 public static void TestCreateRef(ref MyObject m)
24 {
25 m = new MyObject();
26 m.Data = 100;
27 }
28
29 public static void TestCreateNoRef(MyObject m)
30 {
31 m = new MyObject();
32 m.Data = 200;
33 }
34
35 public static void Main()
36 {
37
38 MyObject m = new MyObject();
39 m.Data = 1;
40
41 TestRef(ref m);
42 Console.WriteLine(m.Data);
43
44 TestNoRef(m);
45 Console.WriteLine(m.Data);
46
47 TestCreateRef(ref m);
48 Console.WriteLine(m.Data);
49
50 TestCreateNoRef(m);
51 Console.WriteLine(m.Data);
52 }
53 }
输出结果为:
10 20 100 100
我们可以看到在 TestRef 和 TestNoRef 方法中修改参数的值,相应变量的值都会更改,因为都是传递的引用啊:) 但是在后面 TestCreateRef 和 TestCreateNoRef 两个方法中,它们的结果就不太一样了。
在使用 ref 关键字的方法中重新创建实例的时候,不仅方法中变量的引用被更新(这个当然啦,不然创建实例干嘛呀 :)),而且调用者中变量的引用也被同时更新。将好像是在调用者的范围内使用 new 关键字创建对象一样。
而在不使用 ref 关键字的方法中只是将此方法中的变量的引用更改了,并没有更改调用者变量的引用。也就是说在 TestCreateNoRef 方法中对新创建的变量做任何更改,调用者都不会知道!