程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#基元類型、引用類型和值類型以及裝箱拆箱

C#基元類型、引用類型和值類型以及裝箱拆箱

編輯:C#入門知識

基元類型(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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved