C#值類型和引用類型
與引用類型相對的是值類型。
值類型
當把一個值類型賦給另外一個時,就是對字段成員逐一進行復制,此時在棧上新建了值類型的兩個副本,每一個都可以被獨立操作。
引用類型
和棧中的值類型相比,當對引用類型應用賦值操作符時,我們就是在內存中重定向引用變量的指向。
其中,所有類實例都是引用類型。
按值傳遞引用類型
回顧一下形參和實參
在一般傳值調用的機制中只能把實參傳送給形參,而不能把形參的值反向地傳送給實參。因此在函數調用過程中,形參值發生改變,而實參中的值不會變化。而在引用調用的機制當中是將實參引用的地址傳遞給了形參,所以任何發生在形參上的改變實際上也發生在實參變量上。
參考:https://baike.baidu.com/item/形參/7677757?fr=aladdin
按值傳遞引用類型實例
假設有一個Person類,一個方法:void SendAPersonByValue(Person p)
void SendAPersonByValue(Person p){
//改變"p"的年齡
p.personAge = 99;
//調用者能看到這個重新賦值嗎?
p = new Person("Nikki",99);
}
假設在Main()函數中,調用函數的代碼如下:
Person fred = new Person("Fred",12);
SendAPersonByValue(fred);
結果顯示,fred傳進函數中後,他的personAge被改成了99(p.personAge = 99)
但是函數中的 p = new Person(“Nikki”,99);並未起作用。
結果解釋
值傳遞方式下,形參是複製於實參的。
如果傳入的是值類型,那很簡單,就和預期一樣,形參和實參完全沒有關係。
而如果傳入的是引用類型,那麼會複製指向調用者對象的引用。
即p是一個引用變量,複製於傳進來的fred變量,都指向了內存中的同一處,通過p改變該內存的值,fred引用也會看到變化,但是如果通過p 新建一份的內存區,那就和fred指向的內存區沒有什麼關係了。
按引用傳遞引用類型
如果把之前的函數改寫成按引用傳遞引用類型,其形式如下:(C#語言)
void SendAPersonByValue(ref Person p){
//改變"p"的年齡
p.personAge = 99;
//fred引用變量也會受到影響,p和fred指向了堆上的一個新對象
p = new Person("Nikki",99);
}
此時,Main()函數中的fred引用變量也會受到影響
參考書籍:《精通C#(第六版)Andrew Troelsen》章節4.5