- C# 8.0本質論
- (美)馬克·米凱利斯
- 985字
- 2022-03-30 10:15:08
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 引用類型的實例指向堆
- C++程序設計(第3版)
- Getting started with Google Guava
- 自己動手實現Lua:虛擬機、編譯器和標準庫
- Python入門很簡單
- Developing Mobile Web ArcGIS Applications
- 跟小海龜學Python
- Apache Spark 2 for Beginners
- Spring Cloud、Nginx高并發核心編程
- Java Web應用開發技術與案例教程(第2版)
- Bootstrap Essentials
- Hands-On Microservices with Kotlin
- 零基礎學單片機C語言程序設計
- 用戶體驗增長:數字化·智能化·綠色化
- PySpark Cookbook
- Learning Apache Cassandra