基元類型(primitive type)
----------------------------------
編譯器直接支持的類型。
sbyte / byte / short / ushort / int / uint / long / ulong
char / float / double / bool / decimal /object / string
值類型(value type)
------------------------------
值類型實例分配在堆棧(stack)上,值類型變量本身即包含實例所有字段,值類型不受垃圾回收器控制,在離開作用域後自動釋放所占內存。所有值類型都繼承自ValueType。值類型缺省狀態下(未裝箱)按值復制方式傳遞。
sbyte / byte / short / ushort / int / uint / long / ulong / char / float / double / bool / decimal / 枚舉(enum) / 結構(struct)
引用類型(reference type)
------------------------------------
引用類型都全部或間接繼承自Object,引用對象內存必須在托管堆(heap)中分配,引用類型變量包含對象在托管堆中的內存地址。每個引用類型對象實例都包含一些額外附加成員,且需要垃圾回收器回收才能釋放內存。注意,引用本身在堆棧中分配。引用類型對象傳遞時只是復制引用(內存地址)。
引用對象(Object) / 數組(String) / 數組(Array) / 裝箱後的值類型
引用類型和值類型區別
------------
結構體直接繼承自System.ValueType;而枚舉直接繼承自System.Enum, Enum類又直接繼承自System.ValueType。
下面通過例子看一下他們的區別:
首先定義類和結構體:
class SomeRef { public Int32 x; }
struct SomeVal { public Int32 x; }
1 SomeRef r1 = new SomeRef(); // 分配到堆
2 SomeVal v1 = new SomeVal(); // 分配到棧
3 r1.x =5; // 所引用的堆空間內數據修改
4 v1.x =5; // 直接在棧上復賦值
5 Console.WriteLine(r1.x); // "5"
6 Console.WriteLine(v1.x); // "5"
7 SomeRef r2 = r1; //只把指針復制給了r2
8 SomeVal v2 = v1; // 在棧上分配空間,並且將變量內容進行復制
9 r1.x = 8; // r1指向(也是r2指向)的內容修改
10 v1.x = 9; // 只修改v1內容,v2內容不會受影響
11 Console.WriteLine(r1.x); // "8"
12 Console.WriteLine(r2.x); // "8"
13 Console.WriteLine(v1.x); // "9"
14 Console.WriteLine(v2.x); // "5"
看看下圖的內存分配情況,就一目了然了。
裝箱
-------------
裝箱:將值類型轉換為引用類型。當我們把值類型參數傳遞給需要引用類型參數的方法時,會自動進行裝箱操作。
步驟:
1. 從托管堆分配內存,包括添加方法表指針和SyncBlockIndex。
2. 將值類型字段拷貝到該內存。
3. 返回該地址的引用。
拆箱
------------
拆箱:獲取指向對象中包含的值類型部分的指針。一般拆箱之後會進行字段拷貝操作,兩個操作加起來才是真正與裝箱互反的操作。
步驟:
1. 如果引用為null,拋出NullReferenceException。
2. 如果目標不是已裝箱的值類型,拋出InvalidCastException。
3. 返回指向包含在已裝箱對象中值類型部分的引用,而不是重新在堆棧建立值類型實例,因此需要GC回收才能釋放。
棧(stack)
------------
位於常規內存區(general random-access memory),處理器可以通過棧指針(stack pointer)對它進行直接訪問。指針向下移動創建新的存儲空間,向上釋放存儲空間。是僅次於寄存器(registers)的最快、最有效率的分配內存方法。一般用來存儲那些已知大小的值類型和引用,棧中分配的數據在超出作用域後自動被釋放。
堆(heap)
------------
這是一段多用途內存池(general-purpose pool of memory)。堆的優點是分配內存時編譯器無需知道該分配多少空間,以及數據的生存期。在堆中分配的對象必須通過垃圾回收期回收後才能釋放,因此效率要比棧低一些。
摘自 SamWang