C#程式設計引用型別和值型別 以及引用傳遞和值傳遞
我們從最簡單的說起(基礎知識,懂的同學直接往下拉),直接上程式碼:
static int amount; static void AddTV(int amount) { amount++; Console.WriteLine("方法中,amount="+amount); }
然後,我們將引數amout傳入AddTV()方法,希望能讓其+1
amount = 10; AddTV(amount); Console.WriteLine("AddTV(amount)執行之後,amount=" + amount);
那麼執行的結果呢?
amount的數量並沒有發生變化。
為什麼沒有變呢?
這是最入門的知識,通常的解釋是:
amount是int型別,int是值型別,所以當它作為引數時,傳遞給方法的是它的一個副本(複製品),因此方法中改變的是它的副本的值,amount本身並沒有改變。
ref 關鍵字,如下所示:
static void AddTV(ref int amount) { amount++; Console.WriteLine("方法中,amount="+amount); }
大家自己跑一下,看看結果有什麼不一樣。
這叫做引數的引用傳遞。
這是最基礎的知識,非常清晰。好的,接著,C#是物件導向的語言嘛,我們要引入一個物件。
public class House { public int TVAmount { get; set; } }
然後,我們把House物件作為引數傳遞,值傳遞,不帶ref的。如下所示:
static void AddTV(House house) { house.TVAmount++; Console.WriteLine("方法中,house.TVAmount=" + house.TVAmount); } House house = new House(); AddTV(house); Console.WriteLine("AddTV(house)執行之後,house.TVAmount=" + house.TVAmount);
執行之後你會發現:
咦?house.TVAmount的值變了耶!
為什麼呢?
有的同學聽到的解釋是這樣的:
House是物件,是引用型別,引用型別作為引數傳遞到方法中,它的值會被方法改變。
值型別傳進去不變,引用型別傳進去要變,但值型別引用傳遞又要變……雖然有點繞,但死背下來也行。
講課這些天(五)怎麼才能把程式碼寫好?)
值型別的引用傳遞,和引用型別的值傳遞,效果都一樣,那他們有什麼區別呢?
Good question!
實際上,死背上面的,是會出問題的,我還是用程式碼展示一下:
static void AddTV(House house) { house = new House(); house.TVAmount++; Console.WriteLine("方法中,house.TVAmount=" + house.TVAmount); }
這樣寫,眼尖的同學一眼就能看出差別:這一次方法體內多了一個:house = new House();
不要以為這是抽風啊,實際的開發程式碼中,各種各樣的原因,很多時候都確實會在方法體內重新new一個引數例項的。
那執行結果怎麼樣的呢?
怎麼樣?!引用型別也不好使了?
不像JavaScript到處都是bug和設計缺陷(是的,日常黑js一百年,),C#是一門嚴謹清晰的語言,不會有什麼“靈異”事件。現象和你的想法不一致,一定是你的想法出了問題。
所以,要真正地弄明白這裡面的道道,我們還是要回到原點:
首先的首先,看看這程式碼,你真的明白是什麼意思麼:
House house = new House();
我為什麼要寫成三行?
因為這其實是三個過程:
House house 這是宣告瞭一個變數
new House() 這是生成了一個物件
= 把 house 和 new House() 關聯起來
注意,注意我用的是“關聯”,很多人喜歡說“賦值”,甚至“等於”,這就容易造成我們理解上的誤區。
house和New House,是不同的資料儲存。事實上,在house裡面,有一個記錄了new Houuse()儲存位置的“引用”(reference,這個英文單詞有助於我們理解)。所以,當我們house.TVAmount的時候,是透過house找到new House(),然後得到new House()的資料進行操作。
不知道大家能不能明白這一點?
整個這一塊都是int i,int i 裡面就直接的儲存了10這個資料,沒有引用,int i裡直接存放數值10,所以叫做“值型別”。
好了,理解了上面的概念之後,我們回頭來看方法引數。
C#的說法非常的清晰,只看有沒有 ref 關鍵字:
不帶ref的,一定是“值傳遞”
帶ref的,一定是“引用傳遞”
和傳遞的是什麼型別的引數,半毛錢關係沒有。
關鍵是,你要知道:當引數為引用型別時,傳遞的不是物件(new House()),而是物件的引用(house)。
所以,
如果是值傳遞,傳遞的是 物件引用的 副本
如果是引用傳遞,傳遞的是 物件引用 本身
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2041/viewspace-2799960/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 值傳遞和引用傳遞
- Hellow C# unity學習記錄(7)值型別引用型別以及引數傳遞C#Unity型別
- JavaScript的值傳遞和引用傳遞JavaScript
- Java的值傳遞和引用傳遞Java
- Java中的值傳遞和引用傳遞Java
- Day30--值傳遞和引用傳遞
- 值型別和引用型別型別
- 值傳遞與引用傳遞
- JavaScript值型別和引用型別JavaScript型別
- Swift值型別和引用型別Swift型別
- 關於值傳遞和引用傳遞的解釋
- c#:值型別&引用型別C#型別
- 快速搞懂值傳遞與引用傳遞
- Java 從陣列來看值傳遞和引用傳遞Java陣列
- js中函式引數值傳遞和引用傳遞JS函式
- C#變數型別(1):引用型別和值型別 (轉)變數型別
- C#|.net core 基礎 - 值傳遞 vs 引用傳遞C#
- VB.NET 對於型別的傳遞按值或者按引用型別
- Java - 是值傳遞還是引用傳遞Java
- C#的型別——值型別與引用型別C#型別
- 【C#之值型別vs引用型別】C#型別
- javascript原始值和引用值型別及區別JavaScript型別
- 值型別與引用型別型別
- C# 物件比較(值型別、引用型別)C#物件型別
- js函式引數值傳遞和引用傳遞簡單介紹JS函式
- 解惑4:java是值傳遞還是引用傳遞Java
- golang工作筆記(二)值傳遞與引用傳遞Golang筆記
- java方法中只有值傳遞,沒有引用傳遞Java
- JS是按值傳遞還是按引用傳遞?JS
- 區別值型別資料和引用型別資料型別
- C#引用型別和值型別在堆、棧中的儲存C#型別
- 這一次,徹底解決Java的值傳遞和引用傳遞Java
- ES5中的值傳遞/引用傳遞--解釋
- 從賦值看基本型別和引用型別的區別賦值型別
- Python引用型別和值型別的區別與使用Python型別
- 基本資料型別和引用型別的初始值資料型別
- C# 泛型 引用型別約束 值型別約束C#泛型型別
- JavaScript - 基本型別與引用型別值JavaScript型別