標籤:沒有 span 文章 sdn bar 區別 div tle hive
1.Class為參考型別,Struct為實值型別實值型別與參考型別的區別這兩篇文章講得很好http://www.cnblogs.com/tonney/archive/2011/04/28/2032205.html http://blog.csdn.net/liulong1567/article/details/50678930雖然我們在.net中的架構類庫中,大多是參考型別,但是我們程式員用得最多的還是實值型別。
參考型別如:string,Object,class等總是在從託管堆上分配的,C#中new操作符返回對象的記憶體位址--也就是指向對象資料的記憶體位址。
以下是實值型別與參考型別的表: 從這張圖可以看出,
class(類)執行個體化出來的對象,指向了
記憶體堆中分配的空間
struct(結構)執行個體化出來的對象,是在
記憶體棧中分配
所以,實值型別和參考型別的區別就是:
1、它們儲存的位置不一樣
2、如果是參考型別,當兩個對象指向同一個地方,修改某一個的時候,其它對象的值會發生改變當說到類的執行個體是傳引用時,實際過程是,先擷取一個指標,它指向對象在記憶體中的地址,然後傳遞這個指標。這很重要,因為一個類的執行個體,實際上可能很大,包含了很多域甚至其他對象。在這種情況下,賦值和傳遞整個執行個體可能非常影響效能,這就為什麼要用傳地址來替代。說到傳值時,實際過程是,對這個變數進行全複製/拷貝,然後傳遞這個副本,原始值不變。結構體就是實值型別,它是傳值的。這意味著,結構體是理想的小型資料結構。 由於參考型別在託管堆上分配,它只會在調用記憶體回收時才被清理。實值型別實在記憶體棧上分配,這就說明他們很容易被回收,而且不受記憶體回收的影響。 資料類型分隔為實值型別和參考型別。實值型別要麼是堆棧分配的,要麼是在結構中以內聯方式分配的。參考型別是堆分配的。參考型別和實值型別都是從最終的基類
Object 派生出來的。當實值型別需要充當對象時,就在堆上分配一個封裝(該封裝能使實值型別看上去像引用對象一樣),並且將該實值型別的值複製給它。該封裝被加上標記,以便系統知道它包含一個實值型別。這個進程稱為裝箱,其反向進程稱為unboxing。裝箱和unboxing能夠使任何類型像對象一樣進行處理。
2.Class可以繼承父類,Struct不可以所有結構體都預設繼承System.ValueType父類,所以不能繼承別的父類,ValueType是實值型別的基類,詳見:https://msdn.microsoft.com/zh-cn/library/system.valuetype(VS.80).aspx
3.Struct必須在建構函式對所有變數賦值結構體中所有變數都必須在建構函式中初始化
4.Struct沒有預設建構函式 Struct不允許有參數為空白的建構函式
5.Struct與class的效能上的優缺點關於實值型別與參考型別的記憶體可以看這篇文章:https://msdn.microsoft.com/zh-cn/dd365372 實值型別的執行個體化之後在記憶體的大小就是其所有內容物大小,也就是內容物記憶體越大、佔用記憶體越大,存放在棧中,但是取值更快,不需要GC回收參考型別把值存放在堆中,引用存在棧中,執行個體化時要在堆中取值,所以更消耗時間,但是更省記憶體,因為只用引用指標的大小,需要GC回收
|
實值型別 |
參考型別 |
記憶體 |
大 |
小 |
耗時 |
小 |
大 |
GC |
小 |
大 |
|
|
|
|
|
|
6.Struct類型變數預設不可為空白也就是說,不能寫這個語句 struct != null,如果像這樣做的話,一定要加上?,為它取值要加上Value,判斷是否為空白要用HasValueStruct? struct = *****;if(struct.HasValue) struct.Value.***** = ****;原因參考這篇文章:http://blog.csdn.net/xiaojie_cp/article/details/45892325實值型別後面加問號表示可為空白null(Nullable 結構)Nullable是.NET 2.0中新提供的一種用於標明一個實值型別是否可以為空白的技術。 對於一個類型,如果既可以給它分配一個值,也可以給它分配Null 參考null(表示沒有任何值),我們就說這個類型是可空的。 因此,可空類型可表示一個值,或表示不存在任何值。例如,類似 String 的參考型別就是可空類型,而類似 Int32 的實值型別不是可空類型。Nullable 結構支援將實值型別擴充為可以為null,但不支援在參考型別上使用,因為參考型別本身就是可空的。因為實值型別的容量只夠表示適合於該類型的值,因此它不可為空白;實值型別沒有表示空值所需的額外容量。例:public int? age;
等同 Nullable<int>
7.其他實值型別還有一個特性就是一旦修改值,就會產生一個實值型別的副本參考型別修改值,不會產生副本,但所有有該引用的值都會被修改
8.eg
我們來看下面一段代碼:
首先在類中聲明一個class類,和一個struct結構,
並使用在程式入口調用它們,:
現在我們來看一看,它們在記憶體當中是如何儲存的?
從這張圖可以看出,class(類)執行個體化出來的對象,指向了記憶體堆中分配的空間
struct(結構) 執行個體化出來的對象,是在記憶體棧中分配
接下來,我們再來在上面的程式做如下修改:
紅框,代碼定義一個class執行個體化對象s2,然後把對象s1賦值給s2
藍框,代碼定義一個結構執行個體化對象r2,然後把對象r1賦值給r2
那它們輸出的結果是多少呢?請選擇( )
A、 s1的值為:12 s2的值為222
r1的值為:16 r2的值為666
B、 s1的值為:12 s2的值為222
r1的值為:666 r2的值為666
C、 s1的值為:222 s2的值為222
r1的值為:16 r2的值為666
D、 s1的值為:222 s2的值為222
r1的值為:666 r2的值為666
正確答案是:C
為什麼會這樣呢?所以我們來看一看,多個實值型別和參考型別在記憶體裡面是如何儲存的,
,可以看出,兩個參考型別 s1,s2都指向了同一個拖管堆上的空間,
當某一個發生改變的時候,其於的會發生變化
而結構是實值型別,雖然使用r2=r1,把r1對象賦值給r2,
但是它會線上程棧中分配一個獨立的空間,
當修改某一個對象的值的時候,不會影響到另一個對象
所以,實值型別和參考型別的區別就是:
1、它們儲存的位置不一樣
2、如果是參考型別,當兩個對象指向同一個地方,修改某一個的時候,其它對象的值會發生改變
案例代碼下載
c#中Class和Struct使用與效能的區別