結構體 struct 和 類Class 區別
c#中結構體和類結構相似,夠可以包括資料成員和方法成員。
二者區別:
1,結構是指型別,在棧中分配空間;類引用型別,在堆中分配空間,棧中儲存引用。
2,結構直接儲存成員資料,其成員資料位於堆中;類堆中儲存物件,棧中的引用指向物件。
C#中的簡單型別,如int、double、bool等都是結構型別。
由於結構是值型別,並且直接儲存資料,因此在一個物件的主要成員為資料且資料量不大的情況下,使用結構會帶來更好的效能。
一,struct --結構語法
結構:值型別,每個結構都儲存自己的資料,修改一個結構資料不會影響其他結構。
類:多個引用可以指向同一個物件,對一個引用進行操作,必然會影響另一個,應該慎重。
二,結構賦值
建立結構賦給一個變數p1,則該變數包含結構的全部值。變數p1賦給變數p2時,將p1的全部值複製到p2的棧空間,p1的任何操作與p2無關。
將一個變數賦值給另一個變數時,是把資料從一個結構複製到另一個結構,當資料較多時,這種賦值機制開銷較大。
類中變數間複製的是引用。
結構為值型別,不可賦null值。
三,建構函式
結構型別可以有例項建構函式和靜態建構函式,但不能有解構函式。
1、例項建構函式
結構型別都有一個預定義的,沒有引數的建構函式,這點與類是一樣的。此建構函式不允許刪除和重定義,並且這個無引數的建構函式會一直存在,並不會因為定義了其他帶引數的建構函式就消失,這一點和類不同。
注意如果沒有使用new運算子,是不可以使用資料成員的值(除非已顯示地設定了該資料成員的值)和呼叫函式成員的(除非所有資料成員均已經被賦值)。
四,靜態建構函式
和類一樣,結構型別也可以有靜態建構函式,靜態建構函式用於初始化靜態資料成員。靜態建構函式有如下特點:
1、靜態建構函式不能有訪問修飾符和引數;
2、靜態建構函式不能訪問例項成員;
3、靜態建構函式無法直接進行呼叫;
結構和類的靜態建構函式的觸發規則不同,類的靜態建構函式是在建立第一個例項或引用任何靜態成員之前自動呼叫的,而結構的靜態建構函式在以下情況呼叫:
1、使用顯式宣告的建構函式進行初始化
2、呼叫結構的方法或訪問結構的靜態
五,結構的多型和可繼承性
結構直接派生自System.ValueType,間接派生自System.Object,但結構是隱式密封的,不能作為基類在派生出其他的結構,也不能從類派生,但可以從介面派生。
結構的特性:
1、結構型別總是隱式密封的,因此在定義結構時不能使用sealed和abstract關鍵字;
2、因為結構不能作為基類,結構的成員不能使用如下訪問修飾符:protected和protected,internal;
3、結構的函式成員不能宣告為abstract和virtual,但是可以使用override關鍵字,用以覆寫它的基類System.ValueType中的方法。
六,結構的裝箱與拆箱
結構是值型別,因此當它被轉換為object型別時,或者它所實現的介面型別的時候,就會執行裝箱操作;同樣,當執行相反操作的時候,就會執行拆箱操作。
七,結構和類的對比
結構 類
資料型別 值型別 引用型別
是否必須使用new運算子例項化 否 是
是否可宣告無引數的建構函式 否 是
資料成員可否在宣告的同時初始化 宣告為const或static可以,資料成員不可以 可以
直接派生自什麼型別 System.ValueType 有
是否有解構函式 無 有
可否從類派生 否 可以
可否實現介面 可以 可以
例項化時在棧還是在堆分配記憶體 棧 堆,棧中儲存引用
該型別的變數可否被賦值為null 否 可以
可否定義私有的無參建構函式 否 可以
是否總有一個預設的無參建構函式 是 否
八,效能
因為結構是值型別,因此在為結構分配記憶體,或者當結構超出了作用域被刪除時,效能會非常好,因為他們將內聯或者儲存在堆疊中。當把一個結構型別的變數賦值給另一個結構時,對效能的影響取決於結構的大小,如果結構的資料成員非常多而且複雜,就會造成損失,接下來使用一段程式碼來說明這個問題。
結構和類的適用場合分析:
1、當堆疊的空間很有限,且有大量的邏輯物件時,建立類要比建立結構好一些;
2、對於點、矩形和顏色這樣的輕量物件,假如要宣告一個含有許多個顏色物件的陣列,則CLR需要為每個物件分配記憶體,在這種情況下,使用結構的成本較低;
3、在表現抽象和多級別的物件層次時,類是最好的選擇,因為結構不支援繼承。
4、大多數情況下,目標型別只是含有一些資料,或者以資料為主。