數據的類型定義了存儲數據須要的內存大小及組成該類型的數據成員。類型還決定了對象在內存中的存儲位置——棧或堆。函數
類型被分爲兩種:值類型和引用類型,這兩種類型的對象在內存中的存儲方式不一樣。ui
下圖展現了每種類型的單個數據項是如何存儲的。對於值類型,數據存放在棧裏。對於引用類型,實際數據存放在堆裏而引用存放在棧裏。3d
全部值類型都隱式派生自 System.ValueType
,下表顯示 C# 值類型:code
值類型 | 類別 | 類型後綴 |
---|---|---|
bool |
Boolean |
|
byte |
無符號、數字、整型 | |
char |
無符號、數字、整型 | |
decimal |
數字、浮點 | M 或 m |
double |
數字、浮點 | D 或 d |
enum |
枚舉 | |
float |
數字、浮點 | F 或 f |
int |
帶符號、數字、整型 | |
long |
帶符號、數字、整型 | L 或 l |
sbyte |
帶符號、數字、整型 | |
short |
帶符號、數字、整型 | |
struct |
用戶定義的結構 | |
uint |
無符號、數字、整型 | U 或 u |
ulong |
無符號、數字、整型 | UL 、Ul 、uL 、ul 、LU 、Lu 、lU 或 lu |
ushort |
無符號、數字、整型 |
值類型直接包含值,換言之,變量引用的位置就是內存中實際存儲值的位置。對象
所以,將一個值賦給變量 1,再將變量 1 賦給變量 2,會在變量 2 的位置建立值的拷貝,而不是引用變量 1 的位置。blog
這進一步形成更改變量 1 的值不會影響變量 2 的值。內存
下圖對此進行了演示。number1
引用內存中的特定位置,該位置包含值 42
。將 number1
的值賦給 number2
以後,兩個變量都包含值 42
。但修改其中任何一個值都不會影響另外一個值。ci
相似地,將值類型的實例傳給 Console. WriteLine()
這樣的方法也會生成內存拷貝。在方法內部對參數值進行的任何修改都不會影響調用函數中的原始值。get
引用類型的變量存儲對數據存儲位置的引用,而不是直接存儲數據。要去那個位置才能找到真正的數據。因此爲了訪問數據,「運行時」1 要先從變量中讀取內存位置,再「跳轉」到包含數據的內存位置。it
爲引用類型的變量分配實際數據的內存區域稱爲堆(heap)。
因爲引用類型只拷貝對數據的引用,因此兩個不一樣的變量可引用相同的數據。所以,對一個變量執行的操做會影響另外一個變量所引用的對象。不管賦值仍是方法調用都會如此。所以,若是在方法內部更改引用類型的數據,方法執行完成以後,將看到更改後的結果。
一個類型要麼是值類型,要麼是引用類型。區別在於數據存儲的方式:對於值類型,數據存放在棧裏。對於引用類型,實際數據存放在堆裏而引用存放在棧裏。
引用類型的變量存儲對其數據(對象)的引用,而值類型的變量直接包含其數據。 對於引用類型,兩個變量可引用同一對象;所以,對一個變量執行的操做會影響另外一個變量所引用的對象。 對於值類型,每一個變量都具備其本身的數據副本,對一個變量執行的操做不會影響另外一個變量。