class 和 struct 最本質(zhì)的區(qū)別 : class 是引用類型,它在堆中分配空間蹦渣,棧中保存的只是引用哄芜;而 struct 是值類型,它在棧中分配空間柬唯。
什么是class?
class(類)是面向?qū)ο缶幊痰幕靖拍钪抑颍且环N自定義數(shù)據(jù)結(jié)構(gòu)類型,通常包含字段权逗、屬性美尸、方法、構(gòu)造函數(shù)斟薇、索引器师坎、操作符等。在.NET中堪滨,所有的類都最終繼承自 System.Object 類胯陋,因此是一種引用類型,也就是說袱箱,new 一個(gè)類的實(shí)例時(shí)遏乔,在棧(stack)上存放該實(shí)例在托管堆(Managed Heap)中的地址,而實(shí)例的值保存在托管堆(Managed Heap)中发笔。
托管堆(Managed Heap) :托管堆分配在被操作系統(tǒng)保留的一段內(nèi)存區(qū)域中盟萨,這段內(nèi)存區(qū)域是由 CLR 來管理的,這段內(nèi)存稱之為托管堆了讨。
什么是struct?
struct(結(jié)構(gòu))是一種值類型捻激,用于將一組相關(guān)的變量組織為一個(gè)單一的變量實(shí)體 。所有的結(jié)構(gòu)直接派生自 System.ValueType前计,間接派生自System.Object胞谭,但結(jié)構(gòu)是隱式密封的,不能作為基類再派生出其他的結(jié)構(gòu)男杈,也不能從類派生丈屹,但可以從接口派生。struct 實(shí)例在創(chuàng)建時(shí)分配在線程的棧(stack)上伶棒,它本身存儲(chǔ)了值旺垒。所以在使用 struct 時(shí)彩库,我們可以將其當(dāng)作 int、char 這樣的基本類型對待袖牙。
publicstructAddressBook
{
//構(gòu)造器、字段舅锄、屬性鞭达、方法、事件
}
class是引用類型皇忿,struct是值類型畴蹭;既然 class 是引用類型,class 可以設(shè)為 null鳍烁;但是我們不能將 struct 設(shè)為 null叨襟,因?yàn)樗侵殿愋汀?/p>
當(dāng)你實(shí)例化一個(gè) class,它將創(chuàng)建在【堆】上幔荒。而你實(shí)例化一個(gè) struct糊闽,它將創(chuàng)建在【棧】上爹梁。
你使用的是一個(gè)對 class 實(shí)例的引用右犹。而你使用的不是對一個(gè) struct 的引用(而是直接使用它們)。
當(dāng)我們將 class 作為參數(shù)傳給一個(gè)方法姚垃,我們傳遞的是一個(gè)引用念链。struct 傳遞的是值而非引用。
class 可以定義析構(gòu)器积糯,但是 struct 不可以掂墓。
class可以有顯示的無參構(gòu)造器,但是 struct不可以看成。
class 的構(gòu)造器不需要初始化全部字段君编,struct 的構(gòu)造器必須初始化所有字段。
struct 在聲明時(shí)不能對實(shí)例字段進(jìn)行賦值川慌。
class使用前必須new關(guān)鍵字實(shí)例化(靜態(tài)類除外)啦粹,struct不需要。
class 支持繼承和多態(tài)窘游,struct 不支持唠椭。注意:但是 struct 可以和類一樣實(shí)現(xiàn)接口。
既然 struct 不支持繼承忍饰,其成員不能以 protected?或 protected internal 修飾贪嫂。
class 比較適合大的和復(fù)雜的數(shù)據(jù),struct 適用于作為經(jīng)常使用的一些數(shù)據(jù)組合成的新類型艾蓝。
struct 類型總是隱式密封的力崇,因此在定義結(jié)構(gòu)時(shí)不能使用 sealed 和 abstract 關(guān)鍵字斗塘。
struct的函數(shù)成員不能聲明為 abstract 和 virtual,但是可以使用 override 關(guān)鍵字亮靴,用以覆寫它的基類 System.ValueType 中的方法馍盟。
適用場合:
struct 有性能優(yōu)勢,class 有面向?qū)ο蟮臄U(kuò)展優(yōu)勢.
由于結(jié)構(gòu)是值類型茧吊,并且直接存儲(chǔ)數(shù)據(jù)贞岭,因此在一個(gè)對象的主要成員為數(shù)據(jù)且數(shù)據(jù)量不大的情況下,使用結(jié)構(gòu)會(huì)帶來更好的性能.
將一個(gè)結(jié)構(gòu)變量賦值給另一個(gè)結(jié)構(gòu)變量搓侄,就是把數(shù)據(jù)從一個(gè)結(jié)構(gòu)復(fù)制到另一個(gè)結(jié)構(gòu)瞄桨。而類則不同,在類的變量之間讶踪,復(fù)制的是引用芯侥,而不是類數(shù)據(jù).
當(dāng)把一個(gè)結(jié)構(gòu)類型的變量賦值給另一個(gè)結(jié)構(gòu)時(shí),對性能的影響取決于結(jié)構(gòu)的大小乳讥,當(dāng)數(shù)據(jù)比較大的時(shí)候柱查,這種數(shù)據(jù)復(fù)制機(jī)制會(huì)帶來較大的開銷.
對于點(diǎn)、矩形和顏色這樣的輕量對象云石,假如要聲明一個(gè)含有許多個(gè)顏色對象的數(shù)組物赶,則 CLR 需要為每個(gè)對象分配內(nèi)存,在此情況下留晚,使用結(jié)構(gòu)的成本較低.
當(dāng)堆棧的空間很有限酵紫,且有大量的邏輯對象時(shí),創(chuàng)建類要比創(chuàng)建結(jié)構(gòu)好一些.
在表現(xiàn)抽象和多級別的對象層次時(shí)错维,類是最好的選擇奖地,因?yàn)榻Y(jié)構(gòu)不支持繼承.
用于底層數(shù)據(jù)存儲(chǔ)的類型設(shè)計(jì)為 struct 類型,將用于定義應(yīng)用程序行為的類型設(shè)計(jì)為 class赋焕。如果對類型將來的應(yīng)用情況不能確定参歹,應(yīng)該使用 class.