把數據傳入方法中,可以使方法有多個返回值。
值參數,通過將實參的值復制到形參的方式傳遞數據。值參數的實參可以是變量或者是表達式
下面是一個簡單的值參數傳遞的過程
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 SomeData v1 = new SomeData(); 6 int v2 = 30; 7 Console.WriteLine("v1.value:{0},v2:{1}", v1.value, v2); 8 Calculate(v1, v2); 9 Console.WriteLine("v1.value:{0},v2:{1}", v1.value, v2); 10 11 } 12 13 static void Calculate(SomeData p1, int p2) 14 { 15 Console.WriteLine("p1.value:{0},p2:{1}", p1.value, p2); 16 p1.value += 50; 17 p2 += 50; 18 Console.WriteLine("p1.value:{0},p2:{1}", p1.value, p2); 19 } 20 } 21 22 class SomeData 23 { 24 public int value = 100; 25 }
1、在調用void Calculate(SomeData p1, int p2)方法之前,系統為v1和v2分配內存,v1的引用和v2存儲在棧中,v1的數據存儲在堆中(PS:手繪的圖字寫的丑,圖也畫的丑,這輩子與美術無緣)
2、開始調用方法時,v1是引用類型所以只復制了v1的引用給了p1,v1和p1同時指向堆中的同一個對象;v2是值類型,所以直接把值復制給p2
3、在方法執行的過程中,p1的value字段和p2都加上了50
4、方法執行完成後形參從棧中彈出(展開),最終v2的值沒有改變,v1的值改變了。這也是值類型和引用類型中常會看到的區別。
引用參數,修飾符ref,實參必須是變量,而且必須在調用前賦值。引用參數並不會給形參在內存中開辟新的空間,它只是作為實參的一個別名,在內存中和實參指向的是同一個地址。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 SomeData v1 = new SomeData(); 6 int v2 = 30; 7 Console.WriteLine("v1.value:{0},v2:{1}", v1.value, v2); 8 Calculate(ref v1, ref v2); 9 Console.WriteLine("v1.value:{0},v2:{1}", v1.value, v2); 10 11 } 12 13 static void Calculate(ref SomeData p1, ref int p2) 14 { 15 Console.WriteLine("p1.value:{0},p2:{1}", p1.value, p2); 16 p1.value += 50; 17 p2 += 50; 18 Console.WriteLine("p1.value:{0},p2:{1}", p1.value, p2); 19 } 20 } 21 22 class SomeData 23 { 24 public int value = 100; 25 }
輸出參數,修飾符out,實參也必須是變量,和引用參數有些類似,輸出參數的形參也是作為實參的別名,不同的是輸出參數可以不用對實參進行初始化,但是在函數調用的過程中必須對輸出參數賦值,在沒有賦值之前去使用形參的話是不允許的,無法通過編譯。
1 static void Main(string[] args) 2 { 3 SomeData v1; 4 int v2; 5 Calculate(out v1, out v2); 6 Console.WriteLine("v1.value:{0},v2:{1}", v1.value, v2); 7 8 } 9 10 static void Calculate(out SomeData p1, out int p2) 11 { 12 p1 = new SomeData(); 13 p1.value = 50; 14 p2 = 50; 15 Console.WriteLine("p1.value:{0},p2:{1}", p1.value, p2); 16 } 17 } 18 19 class SomeData 20 { 21 public int value = 100; 22 }
引用類型作為值參數,如果將一個新的對象賦值給形參,將會切斷形參和實參之間的關聯
1 static void Main(string[] args) 2 { 3 SomeData v1 = new SomeData(); 4 Console.WriteLine("v1.value:{0}", v1.value); 5 Calculate(v1); 6 Console.WriteLine("v1.value:{0}", v1.value); 7 } 8 9 static void Calculate(SomeData p1) 10 { 11 p1.value = 60; 12 Console.WriteLine("p1.value:{0}", p1.value); 13 p1 = new SomeData(); 14 p1.value = 50; 15 16 Console.WriteLine("p1.value:{0}", p1.value); 17 } 18 } 19 20 class SomeData 21 { 22 public int value = 100; 23 }
如果將引用類型作為引用參數(用ref修飾符),在上面的例子中的話v1就是指向值為50的數據,並不會消除形參和實參之間的關聯。這裡我就不再畫圖了