MSDN:
參考型別的變數不直接包含其資料;它包含的是對其資料的引用。當通過值傳遞參考型別的參數時,有可能更改引用所指向的資料,如某類成員的值。但是無法更改引用本身的值;也就是說,不能使用相同的引用為新類分配記憶體並使之在塊外保持。若要這樣做,應使用 ref 或 out 關鍵字傳遞參數。為了簡單起見,下面的樣本使用 ref。
下面的樣本示範通過值向 Change 方法傳遞參考型別的參數 arr。由於該參數是對 arr 的引用,所以有可能更改數組元素的值。但是,試圖將參數重新分配到不同的記憶體位置時,該操作僅在方法內有效,並不影響原始變數 arr。
class PassingRefByVal
{
static void Change(int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change is local.
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
}
static void Main()
{
int[] arr = {1, 4, 5};
System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr [0]);
Change(arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);
}
}
輸出
Inside Main, before calling the method, the first element is: 1
Inside the method, the first element is: -3
Inside Main, after calling the method, the first element is: 888
代碼討論
在上個樣本中,數組 arr 為參考型別,在未使用
ref 參數的情況下傳遞給方法。在此情況下,將向方法傳遞指向 arr 的引用的一個副本。輸出顯示方法有可能更改數組元素的內容,在這種情況下,從 1 改為 888。但是,在 Change 方法內使用 new 運算子來分配新的記憶體部分,將使變數 pArray 引用新的數組。因此,這之後的任何更改都不會影響原始數組 arr(它是在 Main 內建立的)。實際上,本樣本中建立了兩個數組,一個在 Main 內,一個在 Change 方法內。 以上引用地址:http://msdn.microsoft.com/zh-cn/library/s6938f28(v=VS.80).aspx
另,樣本:
protected void Button1_Click(object sender, EventArgs e)
{
Class1 obj1 = new Class1();
obj1.Name = "name1";
obj1.ID = "1";
Class1 obj2 = GetObj(obj1);
Response.Write("obj1 => ID:"+obj1.ID+";Name:"+obj1.Name);
Response.Write("<br/>");
Response.Write("obj2 => ID:" + obj2.ID + ";Name:" + obj2.Name);
}
protected Class1 GetObj(Class1 c)
{
c.ID = "3";
Class1 b = new Class1();
b.ID = "2";
b.Name = "name2";
c = b;
return c;
}
輸出結果:
obj1 => ID:3;Name:name1
obj2 => ID:2;Name:name2
個人理解:
對象作為參數傳遞時,傳遞的是對象的引用(即:使用地址)。比如原來對象(obj1)在地址22處,那麼在GetObj方法內,首先對c進行修改,那麼修改的也是地址22處的對象,即obj1對象。當執行語句c=b;時,那麼原本指向22地址的指標被賦予了新的地址,比如33,那麼再對c進行各種操作,那麼操作的目標也只能是地址33處的新對象,與地址為22處的對象obj1再也不發生任何關係了。因此也就出現了以上結果。
由此擴充並推斷出:在方法參數傳遞時,不加out、ref的情況下,c#都是按值傳遞參數的。對於實值型別的參數,拷貝的是值本身。對於引用型對象,也進行拷貝,只不過是拷貝了該對象的指標!
在加out、ref情況下,一旦方法內部有new之類記憶體重新分配語句,系統將對原對象進行重新分配,即將原對象指標將指向新對象地址!
理解不當之處,敬請指出。