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

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 小豆干 的頭像
    小豆干

    小豆干就是我唷

    小豆干 發表在 痞客邦 留言(0) 人氣()