官术网_书友最值得收藏!

3.1 類型的劃分

一個類型要么是值類型,要么是引用類型。區別在于拷貝方式:值類型的數據總是拷貝值;而引用類型的數據總是拷貝引用。

3.1.1 值類型

除了string,本書目前講到的所有預定義類型都是值類型。值類型直接包含值。換言之,變量引用的位置就是內存中實際存儲值的位置。因此,將一個值賦給變量1,再將變量1賦給變量2,會在變量2的位置創建值的拷貝,而不是引用變量1的位置。這進一步造成更改變量1的值不會影響變量2的值。圖3.1對此進行了演示。number1引用內存中的特定位置,該位置包含值42。將number1的值賦給number2之后,兩個變量都包含值42。但修改其中任何一個值都不會影響另一個值。

圖3.1 值類型的實例直接包含數據

類似地,將值類型的實例傳給Console.WriteLine()這樣的方法也會生成內存拷貝。在方法內部對參數值進行的任何修改都不會影響調用函數中的原始值。由于值類型需要創建內存拷貝,因此定義時不要讓它們占用太多內存(通常應該小于16字節)。

3.1.2 引用類型

相反,引用類型的變量存儲對數據存儲位置的引用,而不是直接存儲數據。要去那個位置才能找到真正的數據。所以為了訪問數據,“運行時”要先從變量中讀取內存位置,再“跳轉”到包含數據的內存位置。“運行時”的這種操作稱為“解引用”。為引用類型的變量分配實際數據的內存區域稱為(heap),如圖3.2所示。

引用類型不像值類型那樣要求創建數據的內存拷貝,所以拷貝引用類型的實例比拷貝大的值類型實例更高效。將引用類型的變量賦給另一個引用類型的變量,只會拷貝引用而不需要拷貝所引用的數據。事實上,每個引用總是處理器的“原生大小”:32位處理器拷貝32位引用,64位處理器拷貝64位引用,以此類推。顯然,拷貝對一個大數據塊的引用要比拷貝整個數據塊快得多。

由于引用類型只拷貝對數據的引用,所以兩個不同的變量可引用相同的數據。如果兩個變量引用同一個對象,則當通過一個變量更改了對象的內部數據時,可以通過另一個變量看到對象內部數據的變化。無論賦值還是方法調用都會如此。因此,如果在方法內部更改引用類型的數據,控制返回調用者之后,將看到更改后的結果。有鑒于此,如果對象在邏輯上是固定大小、不可變的值,就考慮定義成值類型。如果邏輯上是可引用、可變的東西,就考慮定義成引用類型。

除了string和自定義類(如Program),本書目前講到的所有類型都是值類型。但大多數類型都是引用類型。雖然偶爾需要自定義的值類型,但更多的還是自定義的引用類型。

圖3.2 引用類型的實例指向堆

主站蜘蛛池模板: 海丰县| 武强县| 宜春市| 五华县| 潮安县| 鹤庆县| 淅川县| 湖口县| 商丘市| 辽源市| 扎赉特旗| 宜章县| 禹州市| 凤台县| 保德县| 惠来县| 平乡县| 潜江市| 兴和县| 油尖旺区| 萨迦县| 贵港市| 和林格尔县| 东光县| 永福县| 宁远县| 榆中县| 阿尔山市| 汶上县| 潼关县| 集贤县| 沂源县| 威远县| 屯门区| 高淳县| 广汉市| 灵寿县| 宿州市| 汕头市| 乌什县| 黄梅县|