1.1 值類(lèi)型和引用類(lèi)型
??C# 中的類(lèi)型一共分為兩類(lèi),一類(lèi)是值類(lèi)型(Value Type)赫冬,一類(lèi)是引用類(lèi)型(Reference Type)承冰。值類(lèi)型包括了結(jié)構(gòu)和枚舉休偶,引用類(lèi)型則包括了類(lèi)、接口暗挑、委托等笋除。還有一種特殊的值類(lèi)型,稱(chēng)為簡(jiǎn)單類(lèi)型(Simple Type)炸裆,比如 byte垃它,int 等,這些簡(jiǎn)單類(lèi)型實(shí)際上是 BCL 基類(lèi)庫(kù)類(lèi)型的別名烹看。比如国拇,聲明一個(gè) int 類(lèi)型,實(shí)際上是聲明一個(gè) System.Int32 結(jié)構(gòu)類(lèi)型惯殊。
??所有的值類(lèi)型都隱式地繼承自 System.ValueType 類(lèi)型(注意 System.ValueType 本身是一個(gè)類(lèi)類(lèi)型)酱吝。之所以說(shuō)是“隱式地”,是因?yàn)樵?C# 代碼中土思,是看不到這個(gè)繼承關(guān)系的务热,這個(gè)關(guān)系只有通過(guò) MSIL 代碼才可以看到。System.ValueType 類(lèi)型和所有的引用類(lèi)型都繼承自System.Object 基類(lèi)浪漠。
說(shuō)明:
??棧(stack)是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)陕习,在內(nèi)存中霎褐,變量會(huì)被分配在棧上來(lái)進(jìn)行操作址愿。堆(heap)是用于為引用類(lèi)型的實(shí)例(對(duì)象)分配空間的內(nèi)存區(qū)域,在堆上創(chuàng)建一個(gè)對(duì)象冻璃,會(huì)將對(duì)象的地址傳給棧上的變量(反過(guò)來(lái)叫變量指向此對(duì)象,或者變量引用此對(duì)象)省艳。
1.1.1 值類(lèi)型
??當(dāng)聲明一個(gè)值類(lèi)型的變量(Variable)的時(shí)候,變量本身包含了值類(lèi)型的全部字段赖晶,該變量會(huì)被分配在線程堆棧(Thread Stack)上遏插。
1.1.2 引用類(lèi)型
??當(dāng)聲明一個(gè)引用類(lèi)型變量纠修,并使用 new 操作符創(chuàng)建引用類(lèi)型實(shí)例的時(shí)候,該引用類(lèi)型的變量會(huì)被分配到線程棧上了牛,變量保存了位于堆上的引用類(lèi)型的實(shí)例的內(nèi)存地址。變量本身不包含任何類(lèi)型所定義的數(shù)據(jù)鹰祸。
1.1.3 簡(jiǎn)單類(lèi)型
??當(dāng)使用“==”對(duì)引用類(lèi)型變量進(jìn)行比較的時(shí)候,比較的 是它們是否指向堆上同一個(gè)對(duì)象蕴坪。敬锐,對(duì)于string類(lèi)型台夺,對(duì)它們的比較實(shí)際上比較的是值,而不是引用(string是 一種特殊的引用類(lèi)型梳星,它的特殊性在于它是不可變類(lèi)型)
舉個(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è)值類(lèi)型轉(zhuǎn)換成等價(jià)的引用類(lèi)型。它的過(guò)程分為這樣幾步:
1)在堆上為新生成的對(duì)象實(shí)例分配內(nèi)存韵吨。該對(duì)象實(shí)例包含數(shù)據(jù)归粉,但它沒(méi)有名稱(chēng)漏峰。
2)將棧上值類(lèi)型變量的值復(fù)制到堆上的對(duì)象中。
3)將堆上創(chuàng)建的對(duì)象的地址返回給引用類(lèi)型變量倔喂。
舉個(gè)例子:
int i = 1; Object boxed = i; Console.WriteLine("Boxed Point: " + boxed);
而拆箱則是將一個(gè)已裝箱的引用類(lèi)型轉(zhuǎn)換為值類(lèi)型:
需要注意的是:拆箱操作需要顯示聲明拆箱后轉(zhuǎn)換的類(lèi)型席噩。它分為兩步來(lái)完成:
1)獲取已裝箱的對(duì)象的地址顾复。
2)將值從堆上的對(duì)象中復(fù)制到堆棧上的值變量中。
舉個(gè)例子
int i = 1; Object boxed = i; int j; j = (int)boxed; // 顯示聲明拆箱后的類(lèi)型
Console.WriteLine("UnBoxed Point: " + j);