1.1 值類型和引用類型
??C# 中的類型一共分為兩類,一類是值類型(Value Type),一類是引用類型(Reference Type)。值類型包括了結構和枚舉,引用類型則包括了類、接口、委托等。還有一種特殊的值類型,稱為簡單類型(Simple Type),比如 byte,int 等,這些簡單類型實際上是 BCL 基類庫類型的別名。比如,聲明一個 int 類型,實際上是聲明一個 System.Int32 結構類型。
??所有的值類型都隱式地繼承自 System.ValueType 類型(注意 System.ValueType 本身是一個類類型)。之所以說是“隱式地”,是因為在 C# 代碼中,是看不到這個繼承關系的,這個關系只有通過 MSIL 代碼才可以看到。System.ValueType 類型和所有的引用類型都繼承自System.Object 基類。
說明:
??棧(stack)是一種后進先出的數(shù)據(jù)結構,在內(nèi)存中,變量會被分配在棧上來進行操作。堆(heap)是用于為引用類型的實例(對象)分配空間的內(nèi)存區(qū)域,在堆上創(chuàng)建一個對象,會將對象的地址傳給棧上的變量(反過來叫變量指向此對象,或者變量引用此對象)。
1.1.1 值類型
??當聲明一個值類型的變量(Variable)的時候,變量本身包含了值類型的全部字段,該變量會被分配在線程堆棧(Thread Stack)上。
1.1.2 引用類型
??當聲明一個引用類型變量,并使用 new 操作符創(chuàng)建引用類型實例的時候,該引用類型的變量會被分配到線程棧上,變量保存了位于堆上的引用類型的實例的內(nèi)存地址。變量本身不包含任何類型所定義的數(shù)據(jù)。
1.1.3 簡單類型
??當使用“==”對引用類型變量進行比較的時候,比較的 是它們是否指向堆上同一個對象。,對于string類型,對它們的比較實際上比較的是值,而不是引用(string是 一種特殊的引用類型,它的特殊性在于它是不可變類型)
舉個例子:
string a = "123456"; string b = "123456"; if(a == b) Console.WriteLine("a Equals to b");
1.1.4 裝箱和拆箱
簡單來說,裝箱就是將一個值類型轉(zhuǎn)換成等價的引用類型。它的過程分為這樣幾步:
1)在堆上為新生成的對象實例分配內(nèi)存。該對象實例包含數(shù)據(jù),但它沒有名稱。
2)將棧上值類型變量的值復制到堆上的對象中。
3)將堆上創(chuàng)建的對象的地址返回給引用類型變量。
舉個例子:
int i = 1; Object boxed = i; Console.WriteLine("Boxed Point: " + boxed);
而拆箱則是將一個已裝箱的引用類型轉(zhuǎn)換為值類型:
需要注意的是:拆箱操作需要顯示聲明拆箱后轉(zhuǎn)換的類型。它分為兩步來完成:
1)獲取已裝箱的對象的地址。
2)將值從堆上的對象中復制到堆棧上的值變量中。
舉個例子
int i = 1; Object boxed = i; int j; j = (int)boxed; // 顯示聲明拆箱后的類型
Console.WriteLine("UnBoxed Point: " + j);