1.以傳值方式傳遞參考型別
以「傳值方式」傳遞參考型別參數時,傳的是參數的位址
它有可能會變更到參考指到的資料,例如類別成員的值。
您無法變更「參考」本身的值;不能指向別的記憶體區塊
以陣列為例,雖然是傳值,但其實傳的是位址,若在方法內直接修改元素仍然會異動到原本呼叫端陣列的值
更改原來陣列的參考是無效的,因為傳值呼叫不允許變更原本陣列的參考,也就是不能指向一個新的陣列
如果要異動「值」或指向新的陣列,要用ref或out達成
例:
在這個例子,傳遞到方法的是指向 arr 參考的複本。
在 Change 方法內使用 new 運算子配置新的記憶體部分,即可使變數 pArray 參考產生另一個新的陣列。
因此,之後的任何變更並不會影響到在 Main 中所產生的原始陣列 arr。
事實上,本範例中建立了兩個陣列:一個在 Main 裡面,另一個在 Change 方法內。
假設有一方法如下
static void Change(int[] pArray) { //1.直接修改元素值,會影響到原本陣列的元素,呼叫端會被改成888 pArray[0] = 888; /*2.更改原來陣列的參考是無效的,因為傳值呼叫不允許變更原本陣列的參考, 也就是不能指向一個新的陣列,這裡只能作用在函數內部, 對本來的陣列沒影響*/ pArray = new int[5] {-3, -1, -2, -3, -4}; //輸出的結果是-3,但原始陣列的值仍為888,不會變更 Console.WriteLine("在方法內,第一個元素值為: {0}", pArray[0]); }
呼叫端
static void Main() { int[] arr = {1, 4, 5}; Console.WriteLine("在Main中,呼叫方法前,第一個元素值為:{0}",arr[0]); Change(arr); Console.WriteLine("在Main中,呼叫方法後,第一個元素值為:{0}",arr[0]); } /* Output: 在Main中,呼叫方法前,第一個元素值為: 1 在方法內,第一個元素值為: -3 在Main中,呼叫方法後,第一個元素值為: 888 */
2.以傳址方式傳遞參考型別
下列範例等同於先前範例中,除了,將ref關鍵字加入至方法標頭和呼叫。
在方法上進行任何變更會影響呼叫程式中的原始變數
傳址呼叫,可以變更改原來陣列的值,也可以變更原本陣列的參考
下面這個例子發生在方法內的所有變更會影響 Main 裡面的原始陣列。
事實上,原始陣列是用 new 運算子重新配置的。
因此,呼叫 Change 方法後,任一個 arr 的參考都會指到 Change 方法內所建立五個元素的陣列。
假設有一方法如下
static void Change(ref int[] pArray) { //直接修改元素,或修改本來陣列的參考,都會影響到原本的陣列 pArray[0] = 888; pArray = new int[5] {-3, -1, -2, -3, -4}; Console.WriteLine("在方法內,第一個元素值為: {0}", pArray[0]); }
呼叫端
static void Main() { int[] arr = {1, 4, 5}; Console.WriteLine("在Main中,呼叫方法前,第一個元素值為:{0}",arr[0]); Change(ref arr); Console.WriteLine("在Main中,呼叫方法後,第一個元素值為:{0}",arr[0]); } /* Output: 在Main中,呼叫方法前,第一個元素值為: 1 在方法內,第一個元素值為: -3 在Main中,呼叫方法後,第一個元素值為: -3 */
3.以傳址方式交換二個參考型別的變數(以字串為例)
二個變數會真正交換值
static void SwapStrings(ref string s1, ref string s2) { string temp = s1; s1 = s2; s2 = temp; Console.WriteLine("在方法內,交換後: {0} {1}", s1, s2); } static void Main() { string str1 = "John"; string str2 = "Smith"; Console.WriteLine("在Main內,交換前: {0} {1}", str1, str2); SwapStrings(ref str1, ref str2); Console.WriteLine("在Main內,交換後: {0} {1}", str1, str2); } /* Output: 在Main內,交換前: John Smith 在方法內,交換後: Smith John 在Main內,交換後: Smith John */
參考來源:
https://books.google.com.tw/books?id=3QjJAwAAQBAJ&pg=SA4-PA34&lpg=SA4-PA34&dq=c%23+%E5%82%B3%E5%80%BC%E5%91%BC%E5%8F%AB&source=bl&ots=xOveYIhO9R&sig=AiKZuAemq_lRkk-dNg8-cfYf4r4&hl=zh-TW&sa=X&ei=RG2SVN7KFIesmAX0-oLwCg&ved=0CCsQ6AEwAzgK#v=onepage&q=c%23%20%E5%82%B3%E5%80%BC%E5%91%BC%E5%8F%AB&f=false
http://www.dotblogs.com.tw/hunterpo/archive/2010/05/02/14978.aspx
http://msdn.microsoft.com/zh-tw/library/9t0za5es.aspx
https://books.google.com.tw/books?id=dyUDBAAAQBAJ&pg=SA5-PA21&lpg=SA5-PA21&dq=c%23%E9%99%A3%E5%88%97%E5%82%B3%E9%81%9E&source=bl&ots=BlvhZzY77L&sig=WLbKolu84ULY2g1-06DDzUypMl4&hl=zh-TW&sa=X&ei=SuiSVJagK-HAmAWI6IGACg&ved=0CBsQ6AEwADge#v=onepage&q=c%23%E9%99%A3%E5%88%97%E5%82%B3%E9%81%9E&f=false
http://msdn.microsoft.com/zh-tw/library/s6938f28.aspx
http://msdn.microsoft.com/zh-tw/library/hyfeyz71.aspx
http://www.dotblogs.com.tw/hunterpo/archive/2010/05/02/14978.aspx
http://www.dotblogs.com.tw/davis/archive/2009/12/30/12737.aspx