C#中的struct與C++中的struct,有很大不同,在C#中class是引用類型,struct卻是值類型,在棧上分配實例,struct是密封的,這意味着它們不能被繼承,和所有值類型一樣,結構類型變量含有自己的數據,因此struct類型的變量不能爲null,倆個結構變量不能引用同一對象。
結構體的賦值
把一個結構賦值給另一個結構,就將一個結構的值複製給另一個結構,這和複製類變量不同,複製類變量時只複製引用。
結構體的成員與實例的創建
結構可以有實例構造函數和靜態構造函數,但不允許有析構函數,C#隱式地爲每個結構提供一個無參數的構造函數,這個構造函數把結構的每個成員設置爲該類型的默認值,值成員設置成它們的默認值,引用成員設置爲null,隱式的無參構造函數對每個struct都存在,而且不能刪除或重定義,即使在重載其他含參的構造函數時,也不需要自實現無參的構造函數,這與C#中的類不同,對於類,編譯器只在沒有其他構造函數聲明時提供隱式的無參構造函數,如果重載了其他構造函數,則需要顯示地聲明無參構造函數,否則在定義變量時將不能使用無參的構造函數。調用一個struct中的構造函數(包括隱式無參構造函數),要使用new運算符(即使不從堆中分配內存也要使用new運算符)。
也可以不使用new運算符創建結構的實例,這樣的話就不會調用到構造函數,然而這樣做會有一些限制:
(1)只有在顯式設置數據成員之後,才能使用它們的值
(2)只有在對所有數據成員賦值之後,才能調用任何函數成員
靜態構造函數:與C#中的類相似,結構的靜態構造函數創建並初始化靜態數據成員,並且不能引用實例成員,與類的靜態構造函數規則一樣,以下倆種行爲,任意一種發生之前,將會調用靜態構造函數:
(1)調用顯示聲明的構造函數
(2)引用結構的靜態成員
字段不能在結構體中初始化
在結構中字段初始化語句是不允許的
struct A
{
//public int a=10; 會造成編譯錯誤
public int a;
}
結構是密封的
結構總是隱式密封的,因此結構不支持繼承,因此不能在結構成員聲明時使用protected、internal、abstract、virtual這些修飾符,結構體本身派生自System.ValueType,System.ValueType派生自object,所以可以使用new、override修飾符,當創建一個和基類System.ValueType的成員有相同名稱的成員時就可以使用這倆個修飾符。
結構體作爲返回值和參數
結構體可以用作返回值和參數
返回值:當結構作爲返回值時,將創建它的副本並從函數成員返回
值參數:當結構被用作值參數時,將創建實參結構的副本,該副本用於方法的執行中
ref和out參數:如果把一個結構用作ref、out參數,傳入方法的是該結構的一個引用,這樣就可以修改其數據成員
C#中結構體與類的區別
(1)類是引用類型,結構是值類型
(2)結構不支持繼承
(3)結構不能聲明默認的構造函數和析構函數
(4)類只能通過new來實例化,而結構可以不通過new來實例化
(4)正常情況下類的對象是存儲在堆空間中,結構存儲在棧空間,堆空間大、訪問速度慢,棧空間小、訪問速度快,故而當我們描述一個輕量級對象的時候,結構可提高效率,成本更低,當然也得從需求出發,假如在傳值的時候希望傳遞的是對象的引用而不是對象的拷貝,就應該使用類了
結構體的其他信息
(1)對結構進行分配比創建類的實例開銷小,所以使用結構體代替類有時可以提高性能,但要注意到裝箱和拆箱的高代價
(2)預定義簡單類型(int、short、long等)儘管在.NET和C#中被視爲原始類型,實際上在.NET中都實現爲結構
(3)可以使用與聲明分部類相同的方法聲明分部結構