值類型和引用類型
C# 支持兩種變量類型:
• 值類型 — 這些是內置的基本數據類型,例如 char、int、float 和用 struct 聲明的用戶定義類型。 • 引用類型 — 從基本類型構造而來的類和其他復雜數據類型。這種類型的變量並不包含類型的實例,而只是包含對實例的引用。讓我們略微深入地研究一下這個問題。如果我們創建兩個值類型變量 i 和 j,比如:
int i = 10;
int j = 20;
圖 1:值類型的內存位置
則 i 和 j 彼此完全獨立,並且分配了不同的內存位置:
如果我們改變這些變量中的某一個的值,另一個自然不會受到影響。例如,如果我們有一個這樣的表達式:
int k = i;
則變量之間仍然沒有聯系。也就是說,之後如果我們改變 i 的值,k 還會保留賦值時 i 具有的值。
然而,引用類型的做法卻不同。例如,我們可以這樣聲明兩個變量:
myClass a = new myClass();
myClass b = a;
現在,因為類是 C# 中的引用類型,所以 a 稱為對 myClass 的引用。上面兩行中的第一行在內存中創建了 myClass 的一個實例,並且將 a 設置為引用該實例。因此,當我們將 b 設置為等於 a 時,它就包含了對內存中類的引用的重復。如果我們現在改變 b 中的屬性,a 中的屬性就將反映這些改變,因為這兩者都指向內存中的相同對象,如下圖所示:
圖 2:引用類型的內存位置
裝箱 (Boxing) 和拆箱 (Unboxing)
這種將值類型轉換為引用類型的過程稱為裝箱。而相反的將引用類型轉換為值類型的過程就稱為拆箱。如下面的代碼所示:
int valueVariable = 10;
// boxing
object obj = refVariable;
// unboxing
int valueVariable = (int) refVariable;
Java 需要我們手動執行這樣的轉換。通過構造這樣的對象,可以將基本數據類型轉換成包裝類的對象(裝箱)。同樣,通過調用這種對象中的適當方法,也可以從包裝類的對象中提取基本數據類型的值(拆箱)。