从堆栈浅析c#的ref、out关键字
篇外话:老了,是睡不好醒得早的充分条件还是充分必要条件呢?如果是后者,我是不是可以认为,睡不好,是因为我老了。。。。6点多起来纠结这篇文,好歹也是技术博,不能连篇门面都没。。。。。
msdn中对ref关键字的介绍为:ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。传递到ref 参数的参数必须最先初始化。这与 out 不同,后者的参数在传递之前不需要显式初始化。因为ref和out仅仅是在运行时的处理方式不同,但在编译时的处理方式相同的。这点可以通过反编译的文件可以看出,不赘述。基于此点,本文只单独分析ref关键字,out大同小异,亦不赘述,读者自己构建相同的代码分析可得。
在csdn中有一篇“对于关键字Ref和Out的理解”,原文有点小错,我基于那个文和代码,下面做一定的额外分析。感谢原文作者。先贴代码,然后具体分析。(点击+号展开代码)
Code
1private void button1_Click(object sender, EventArgs e)
2 {
3 int[] firstArray = {1, 2, 3};
4 int[] firstArrayCopy = firstArray;
5 this.label1.Text = "Test Passing firstArray reference by value";
6 this.label1.Text += "\n\nContents of firstArray before calling FirstDouble:\n\t";
7
8 for(int i = 0;i < firstArray.Length; i++)
9 {
10 this.label1.Text += firstArray[i] + " ";
11 }
12 unsafe
13 {
14 fixed (int* p = &firstArray[0])
15 {};
16 }
17
18
19 FirstDouble(firstArray);
20
21 unsafe
22 {
23 fixed (int* d = &firstArray[0])
24 { };
25 }
26
27 this.label1.Text += "\n\nContents of firstArray after calling FirstDouble.\n\t";
28 for(int i=0;i < firstArray.Length; i++)
29 {
30 this.label1.Text += firstArray[i] + " ";
31 }
32 if(firstArray == firstArrayCopy)
33 this.label1.Text +="\n\nThe references refer to the same array.\n";
34 else
35 this.label1.Text +="\n\nThe reference refer to different arrays.\n";
36
37
38 int[] secondArray = {1, 2, 3};
39 int[] secondArrayCopy = secondArray;
40
41 this.label1.Text += "\nTest passing secondArray reference by reference.";
42 this.label1.Text += "\n\nContents of secondArray before calling SecondDouble:\n\t";
43 for(int i=0;i < secondArray.Length; i++)
44 {
45 this.label1.Text += secondArray[i] + " ";
46 }
47
48 unsafe
49 {
50 fixed (int* q = &secondArray[0])
51 { };
52 }
53 SecondDouble(ref secondArray);
54
55 unsafe
56 {
57 fixed (int* f = &secondArray[0])
58 { };
59 }
60 this.label1.Text +="\n\nContents of secondArray after calling SecondDouble:\n\t";
61
62 for(int i=0; i < secondArray.Length; i++)
63 {
64 this.label1.Text += secondArray[i] + " ";
65 }
66 if(secondArray== secondArrayCopy)
67 this.label1.Text += "\n\nThe reference refer to the same array.";
68 else
69 this.label1.Text += "\n\nThe reference refer to different arrays.";
70 this.label1.Text += "\n___________________heshi_________________\nsecondarray\n";
71 for(int i = 0;i < secondArray.Length; i++)
72 {
73 this.label1.Text += secondArray[i] + " ";
74 }
75
76 this.label1.Text +="\nsecondarraycopy\n";
77 for(int i=0;i < secondArray.Length; i++)
78 {
79 this.label1.Text += secondArrayCopy[i] + " ";
80 }
81
82 }
83 private void FirstDouble(int[] array)
84 {
85 for(int i = 0;i < array.Length; i++)
86 {
87 array[i] *= 2;
88 }
89 unsafe
90 {
91 fixed (int* x = &array[0])
92 {
93 }
94 }
95
96
97
98 array = new int[] {11, 12, 13};
99
100 unsafe
101 {
102 fixed (int* y = &array[0])
103 {
104 }
105 }
106
107
108 }
109 private void SecondDouble(ref int[] array)
110 {
111 for(int i=0;i < array.Length; i++)
112 {
113 array[i] *= 2;
114 }
115 unsafe
116 {
117 fixed (int* m = &array[0])
118 {
119 }
120 }
121 array = new int[] {11, 12, 13};
122 unsafe
123 {
124 fixed (int* n = &array[0])
125 {
126 }
127 }
128 }
1private void button1_Click(object sender, EventArgs e)
2 {
3 int[] firstArray = {1, 2, 3};
4 int[] firstArrayCopy = firstArray;
5 this.label1.Text = "Test Passing firstArray reference by value";
6 this.label1.Text += "\n\nContents of firstArray before calling FirstDouble:\n\t";
7
8 for(int i = 0;i < firstArray.Length; i++)
9 {
10 this.label1.Text += firstArray[i] + " ";
11 }
12 unsafe
13 {
14 fixed (int* p = &firstArray[0])
15 {};
16 }
17
18
19 FirstDouble(firstArray);
20
21 unsafe
22 {
23 fixed (int* d = &firstArray[0])
24 { };
25 }
26
27 this.label1.Text += "\n\nContents of firstArray after calling FirstDouble.\n\t";
28 for(int i=0;i < firstArray.Length; i++)
29 {
30 this.label1.Text += firstArray[i] + " ";
31 }
32 if(firstArray == firstArrayCopy)
33 this.label1.Text +="\n\nThe references refer to the same array.\n";
34 else
35 this.label1.Text +="\n\nThe reference refer to different arrays.\n";
36
37
38 int[] secondArray = {1, 2, 3};
39 int[] secondArrayCopy = secondArray;
40
41 this.label1.Text += "\nTest passing secondArray reference by reference.";
42 this.label1.Text += "\n\nContents of secondArray before calling SecondDouble:\n\t";
43 for(int i=0;i < secondArray.Length; i++)
44 {
45 this.label1.Text += secondArray[i] + " ";
46 }
47
48 unsafe
49 {
50 fixed (int* q = &secondArray[0])
51 { };
52 }
53 SecondDouble(ref secondArray);
54
55 unsafe
56 {
57 fixed (int* f = &secondArray[0])
58 { };
59 }
60 this.label1.Text +="\n\nContents of secondArray after calling SecondDouble:\n\t";
61
62 for(int i=0; i < secondArray.Length; i++)
63 {
64 this.label1.Text += secondArray[i] + " ";
65 }
66 if(secondArray== secondArrayCopy)
67 this.label1.Text += "\n\nThe reference refer to the same array.";
68 else
69 this.label1.Text += "\n\nThe reference refer to different arrays.";
70 this.label1.Text += "\n___________________heshi_________________\nsecondarray\n";
71 for(int i = 0;i < secondArray.Length; i++)
72 {
73 this.label1.Text += secondArray[i] + " ";
74 }
75
76 this.label1.Text +="\nsecondarraycopy\n";
77 for(int i=0;i < secondArray.Length; i++)
78 {
79 this.label1.Text += secondArrayCopy[i] + " ";
80 }
81
82 }
83 private void FirstDouble(int[] array)
84 {
85 for(int i = 0;i < array.Length; i++)
86 {
87 array[i] *= 2;
88 }
89 unsafe
90 {
91 fixed (int* x = &array[0])
92 {
93 }
94 }
95
96
97
98 array = new int[] {11, 12, 13};
99
100 unsafe
101 {
102 fixed (int* y = &array[0])
103 {
104 }
105 }
106
107
108 }
109 private void SecondDouble(ref int[] array)
110 {
111 for(int i=0;i < array.Length; i++)
112 {
113 array[i] *= 2;
114 }
115 unsafe
116 {
117 fixed (int* m = &array[0])
118 {
119 }
120 }
121 array = new int[] {11, 12, 13};
122 unsafe
123 {
124 fixed (int* n = &array[0])
125 {
126 }
127 }
128 }