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

