在C#裡面,所有的型別都是.NET Framework類別庫中的類別,而所有類別都是繼承自類別庫的System.Object。連在我們撰寫一個class的過程中,C#都會幫我們的類別自動繼承於System.Object,所以我們可以說包括型別在內,C#裡面所有東西都是物件。
實值型別(value type)有些書上翻譯成數值型別。算是一種簡單的型別,可以想成長度或佔用記憶體空間固定,包含struct(結構)與enum(列舉),其特性是不能再被繼承,也不會有型別成員(type member),所以不會產生複雜結構,在C#中宣告為struct或enum背後會自動繼承System.ValueType。
參考型別(reference type)有些書上翻譯成參照型別。能形成複雜的型別,包含class(類別)、interface(介面)等等,可以擁有型別成員形成複雜結構,背後會自動繼承System.Object。
雖說所以型別都是物件,但是每個物件因在記憶體中的存放方式不同而有所不同,分為存放在堆疊(stack)與存放在堆積(heap)兩種,記憶體中談論的stack&heap與在資料結構談論的不同,記憶體中指的是物件統一照先後順序排列地方叫做堆疊(stack),使用上是後放先拿出,先進後出,而在記憶體中物件不用照順序排列,放入取出不管順序的地方叫堆積(heap),程式執行時CLR拿到一塊記憶體空間後會自己切出堆疊(stack)區與堆積(heap)區,並幫我們作記憶體控管(包含記憶體安全與記憶體回收),不同的程式語言作法可能都不相同,在C#(.net)會把實值型別放在堆疊(stack),參考型別放在堆積(heap)。
實值型別傳遞給其他人時是複製實值傳遞,參考型別傳遞給其他人時是複製地址傳遞。實值似影印傳遞,會複製成兩份一模一樣的物件,參考傳遞似網址傳遞,會複製網址分享對方,兩人共同觀看網站同一個物件。
實值型別會繼承自System.ValueType(儘管System.ValueType也是繼承自System.Object),而參考型別是繼承自System.Object。而繼承自System.ValueType後會擁有不能再被繼承的特性。
以原始碼上的差異是宣告為struct(結構)的是實質型別(自動繼承自System.ValueType),宣告class(類別)為參考型別(自動繼承自System.Object)。在繼承能力上也有差異,繼承自System.ValueType的物件不能再被繼承。
我們可以從https://referencesource.microsoft.com
看到微軟提供的.NET Framework原始碼
宣告為實值型別如整數或浮點數並不一定是存放在堆疊(stack)裡,視情況而定,例如:我們可以在一個class裡面放入欄位與方法(在C++稱為資料成員與成員函數),所以一個class裡面可能會有宣告為實值型別(例如:int)的欄位,在實體化這個物件後,這個int欄位會連同類別存放在堆積(heap)中,而執行物件的方法時,方法中的int變數會存放在堆疊(stack)中。
原始型別又可以稱位內建型別,本質上是.NET Framework類別庫提供。
別名 | 類別 |
---|---|
bool | System.Boolean |
sbyte | System.Sbyte |
short | System.Int16 |
int | System.Int32 |
double | System.Double |
DateTime | System.DateTime |
別名 | 類別 |
---|---|
object | System.Object |
string | System.String |