目錄
- 值型別
- 參考型別
- 總結
資料的型別定義了存盤資料需要的記憶體大小及組成該型別的資料成員,型別還決定了物件在記憶體中的存盤位置——堆疊或堆,
型別被分為兩種:值型別和參考型別,這兩種型別的物件在記憶體中的存盤方式不同,
- 值型別只需要一段單獨的記憶體,用于存盤實際的資料,
- 參考型別需要兩段記憶體,
- 第一段存盤實際的資料,它總是位于堆中,
- 第二段是一個參考,指向資料在堆中的存放位置,
下圖展示了每種型別的單個資料項是如何存盤的,對于值型別,資料存放在堆疊里,對于參考型別,實際資料存放在堆里而參考存放在堆疊里,
值型別
所有值型別都隱式派生自 System.ValueType,下表顯示 C# 值型別:
| 值型別 | 類別 | 型別后綴 |
|---|---|---|
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 的位置,
這進一步造成更改變數 1 的值不會影響變數 2 的值,
下圖對此進行了演示,number1 參考記憶體中的特定位置,該位置包含值 42,將 number1 的值賦給 number2 之后,兩個變數都包含值 42,但修改其中任何一個值都不會影響另一個值,
類似地,將值型別的實體傳給 Console. WriteLine() 這樣的方法也會生成記憶體拷貝,在方法內部對引數值進行的任何修改都不會影響呼叫函式中的原始值,
參考型別
參考型別的變數存盤對資料存盤位置的參考,而不是直接存盤資料,要去那個位置才能找到真正的資料,所以為了訪問資料,“運行時”[1] 要先從變數中讀取記憶體位置,再“跳轉”到包含資料的記憶體位置,
為參考型別的變數分配實際資料的記憶體區域稱為堆(heap),
由于參考型別只拷貝對資料的參考,所以兩個不同的變數可參考相同的資料,因此,對一個變數執行的操作會影響另一個變數所參考的物件,無論賦值還是方法呼叫都會如此,因此,如果在方法內部更改參考型別的資料,方法執行完成之后,將看到更改后的結果,
總結
一個型別要么是值型別,要么是參考型別,區別在于資料存盤的方式:對于值型別,資料存放在堆疊里,對于參考型別,實際資料存放在堆里而參考存放在堆疊里,
參考型別的變數存盤對其資料(物件)的參考,而值型別的變數直接包含其資料, 對于參考型別,兩個變數可參考同一物件;因此,對一個變數執行的操作會影響另一個變數所參考的物件, 對于值型別,每個變數都具有其自己的資料副本,對一個變數執行的操作不會影響另一個變數,
“運行時”的內容請參考這篇文章:https://www.vinanysoft.com/c-sharp-basics/introducing/managed-execution-and-the-common-language-infrastructure/ ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/91577.html
標籤:C#
上一篇:C# 中的堆疊和堆
