C#的方法參數中,預設都是傳值,但是有一種情況很容易被乎略並誤用,也就是說,你有可能會以為是傳值(by value),可是事實上是傳址(by reference)才對。
大要要注意一件事,就是在實值類型(Value Types),或稱為基礎型別,例如:int, double...等,套用在方法中的參數都是傳值(by value)沒錯,但是如果傳入的東西已經是物件,那就會變成參考到同一個記憶體位址,這時候就會變成傳址(by reference)了。以下用簡單的程式碼重演這個問題。
using System; class Program { private static int[] aryTest = {0, 1, 2, 3}; static void Main() { disp(); change(aryTest); //change value disp(); } static void change(int[] aryTemp) { aryTemp[0] = 5; } static void disp() { foreach(int temp in aryTest) { Console.Write(temp.ToString()); } Console.WriteLine(); } }
輸出是: 0123 5123
注意重點:
下方再舉出一個例子,這裡使用到.NET裡的System.Collection裡面的ArrayList物件,一樣會出現這個問題,藉此提醒使用者注意!
using System; using System.Collections; class Program { private static ArrayList myAL = new ArrayList(); static void Main() { myAL.Add("Hello"); myAL.Add("World"); myAL.Add("!"); disp(); change(myAL); //change value disp(); } static void change(ArrayList tempAL) { tempAL.Remove("World"); } static void disp() { foreach(object oObj in myAL) { Console.Write(oObj.ToString()); } Console.WriteLine(); } }
輸出是: HelloWorld! Hello!
但是話說回來啦,如果你是當成By Value的心態,進行鬆藕合的切割觀點來撰寫,也就是傳入與傳出都是真正用ArrayList丟來丟去,老實說除了一次傳址的CPU運算資源外(這個在現代CPU的運算速度觀點來看根本等於0秒),我個人認為並無不會影響到其它的程式運作,在進行程式設計師最愛的Copy-Paste時更顯優勢!下方程式碼多加了回傳ArrayList的觀念範例。(注意!這樣的做法是多餘的,我只是在演譯這樣寫也無妨)
using System; using System.Collections; class Program { private static ArrayList myAL = new ArrayList(); static void Main() { myAL.Add("Hello"); myAL.Add("World"); myAL.Add("!"); disp(); myAL = change(myAL); //change value disp(); } static ArrayList change(ArrayList tempAL) { tempAL.Remove("World"); return tempAL; } static void disp() { foreach(object oObj in myAL) { Console.Write(oObj.ToString()); } Console.WriteLine(); } }
輸出依然是: HelloWorld! Hello!CSharp Method Arguments Array Object ByValue ByReference